diff options
author | tobrun <tobrun.van.nuland@gmail.com> | 2018-07-17 15:05:53 +0200 |
---|---|---|
committer | Tobrun <tobrun@mapbox.com> | 2018-08-24 18:40:11 +0200 |
commit | d297bf10ef89e97da30e1a00dd49560e18bcb3f0 (patch) | |
tree | 7f7eea2ffd8125777d258a62683d3ffbeb66820f /platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/module | |
parent | 0f58d956d7b525f3722f24494784c8b97801105a (diff) | |
download | qtlocation-mapboxgl-d297bf10ef89e97da30e1a00dd49560e18bcb3f0.tar.gz |
[android] - modularise the sdk
Diffstat (limited to 'platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/module')
3 files changed, 416 insertions, 0 deletions
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/module/http/HttpRequestImpl.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/module/http/HttpRequestImpl.java new file mode 100644 index 0000000000..3195022d3a --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/module/http/HttpRequestImpl.java @@ -0,0 +1,179 @@ +package com.mapbox.mapboxsdk.module.http; + +import android.os.Build; +import android.support.annotation.NonNull; +import android.text.TextUtils; +import android.util.Log; +import com.mapbox.mapboxsdk.BuildConfig; +import com.mapbox.mapboxsdk.constants.MapboxConstants; +import com.mapbox.mapboxsdk.http.HttpRequest; +import com.mapbox.mapboxsdk.http.HttpIdentifier; +import com.mapbox.mapboxsdk.http.HttpLogger; +import com.mapbox.mapboxsdk.http.HttpResponder; +import com.mapbox.mapboxsdk.http.HttpRequestUrl; +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 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.module.http.HttpRequestUtil.toHumanReadableAscii; + +public class HttpRequestImpl implements HttpRequest { + + private static final String userAgentString = toHumanReadableAscii( + String.format("%s %s (%s) Android/%s (%s)", + HttpIdentifier.getIdentifier(), + 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 Call call; + + @Override + public void executeRequest(HttpResponder httpRequest, long nativePtr, String resourceUrl, + String etag, String modified) { + OkHttpCallback callback = new OkHttpCallback(httpRequest); + try { + HttpUrl httpUrl = HttpUrl.parse(resourceUrl); + if (httpUrl == null) { + HttpLogger.log(Log.ERROR, String.format("[HTTP] Unable to parse resourceUrl %s", resourceUrl)); + return; + } + + final String host = httpUrl.host().toLowerCase(MapboxConstants.MAPBOX_LOCALE); + resourceUrl = HttpRequestUrl.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) { + HttpLogger.logRequestUrl = enabled; + } + + public static void enableLog(boolean enabled) { + HttpLogger.logEnabled = enabled; + } + + public static void setOkHttpClient(OkHttpClient okHttpClient) { + HttpRequestImpl.client = okHttpClient; + } + + private static class OkHttpCallback implements Callback { + + private HttpResponder httpRequest; + + OkHttpCallback(HttpResponder 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()) { + HttpLogger.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"; + HttpLogger.log(Log.DEBUG, String.format("[HTTP] Request with response = %s: %s", response.code(), message)); + } + + ResponseBody responseBody = response.body(); + if (responseBody == null) { + HttpLogger.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 (HttpLogger.logEnabled && call != null && call.request() != null) { + String requestUrl = call.request().url().toString(); + HttpLogger.logFailure(type, errorMessage, requestUrl); + } + httpRequest.handleFailure(type, errorMessage); + } + + 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; + } +}
\ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/module/http/HttpRequestUtil.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/module/http/HttpRequestUtil.java new file mode 100644 index 0000000000..66031ea724 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/module/http/HttpRequestUtil.java @@ -0,0 +1,64 @@ +package com.mapbox.mapboxsdk.module.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. + * <p> + * This configuration will outlast the lifecycle of the Map. + * </p> + * + * @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. + * <p> + * Requires {@link #setLogEnabled(boolean)} to be activated. + * </p> + * <p> + * This configuration will outlast the lifecycle of the Map. + * </p> + * + * @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/src/main/java/com/mapbox/mapboxsdk/module/telemetry/TelemetryImpl.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/module/telemetry/TelemetryImpl.java new file mode 100644 index 0000000000..4a0b425a86 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/module/telemetry/TelemetryImpl.java @@ -0,0 +1,173 @@ +package com.mapbox.mapboxsdk.module.telemetry; + +import android.content.Context; +import com.mapbox.android.telemetry.AppUserTurnstile; +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.android.telemetry.SessionInterval; +import com.mapbox.android.telemetry.TelemetryEnabler; +import com.mapbox.mapboxsdk.BuildConfig; +import com.mapbox.mapboxsdk.Mapbox; +import com.mapbox.mapboxsdk.log.Logger; +import com.mapbox.mapboxsdk.maps.TelemetryDefinition; + +import java.lang.reflect.Field; + +public class TelemetryImpl implements TelemetryDefinition { + + private static final String TAG = "Mbgl-TelemetryImpl"; + private static TelemetryImpl instance; + private MapboxTelemetry telemetry; + + /** + * Get a single instance of TelemetryImpl. + * + * @return instance of Telemetry + * @deprecated reference instance from Mapbox.java instead + */ + @Deprecated + public static synchronized TelemetryImpl getInstance() { + if (instance == null) { + instance = new TelemetryImpl(); + } + return instance; + } + + private TelemetryImpl() { + Context appContext = Mapbox.getApplicationContext(); + String accessToken = Mapbox.getAccessToken(); + telemetry = new MapboxTelemetry(appContext, accessToken, BuildConfig.MAPBOX_EVENTS_USER_AGENT); + TelemetryEnabler.State telemetryState = TelemetryEnabler.retrieveTelemetryStateFromPreferences(); + if (TelemetryEnabler.State.ENABLED.equals(telemetryState)) { + telemetry.enable(); + } + } + + /** + * Register the app user turnstile event + */ + @Override + public void onAppUserTurnstileEvent() { + 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)); + } + + /** + * Register an end-user gesture interaction event. + * + * @param eventType type of gesture event occurred + * @param latitude the latitude value of the gesture focal point + * @param longitude the longitude value of the gesture focal point + * @param zoom current zoom of the map + */ + @Override + public void onGestureInteraction(String eventType, double latitude, double longitude, double zoom) { + MapEventFactory mapEventFactory = new MapEventFactory(); + MapState state = new MapState(latitude, longitude, zoom); + state.setGesture(eventType); + telemetry.push(mapEventFactory.createMapGestureEvent(Event.Type.MAP_CLICK, state)); + } + + /** + * Set the end-user selected state to participate or opt-out in telemetry collection. + */ + @Override + public void setUserTelemetryRequestState(boolean enabledTelemetry) { + if (enabledTelemetry) { + TelemetryEnabler.updateTelemetryState(TelemetryEnabler.State.ENABLED); + telemetry.enable(); + } else { + telemetry.disable(); + TelemetryEnabler.updateTelemetryState(TelemetryEnabler.State.DISABLED); + } + } + + /** + * Set the debug logging state of telemetry. + * + * @param debugLoggingEnabled true to enable logging + */ + @Override + public void setDebugLoggingEnabled(boolean debugLoggingEnabled) { + telemetry.updateDebugLoggingEnabled(debugLoggingEnabled); + } + + /** + * Set the telemetry rotation session id interval + * + * @param interval the selected session interval + * @return true if rotation session id was updated + */ + @Override + public boolean setSessionIdRotationInterval(int interval) { + return telemetry.updateSessionIdRotationInterval(new SessionInterval(interval)); + } + + /** + * Set the debug logging state of telemetry. + * + * @param debugLoggingEnabled true to enable logging + * @deprecated use {@link #setDebugLoggingEnabled(boolean)} instead + */ + @Deprecated + public static void updateDebugLoggingEnabled(boolean debugLoggingEnabled) { + TelemetryDefinition definition = Mapbox.getTelemetry(); + if (definition != null) { + definition.setDebugLoggingEnabled(debugLoggingEnabled); + } + } + + /** + * Update the telemetry rotation session id interval + * + * @param interval the selected session interval + * @return true if rotation session id was updated + * @deprecated use {@link #setSessionIdRotationInterval(int)} instead + */ + @Deprecated + public static boolean updateSessionIdRotationInterval(SessionInterval interval) { + try { + Field field = interval.getClass().getDeclaredField("interval"); + field.setAccessible(true); + Integer intervalValue = (Integer) field.get(interval); + TelemetryDefinition definition = Mapbox.getTelemetry(); + if (definition != null) { + return definition.setSessionIdRotationInterval(intervalValue); + } + } catch (Exception exception) { + Logger.e(TAG, "Exception occurred when updating session id rotation interval", exception); + } + return false; + } + + /** + * Method to be called when an end-user has selected to participate in telemetry collection. + * + * @deprecated use {@link #setUserTelemetryRequestState(boolean)} with parameter true instead + */ + @Deprecated + public static void enableOnUserRequest() { + TelemetryDefinition definition = Mapbox.getTelemetry(); + if (definition != null) { + definition.setUserTelemetryRequestState(true); + } + } + + /** + * Method to be called when an end-user has selected to opt-out of telemetry collection. + * + * @deprecated use {@link #setUserTelemetryRequestState(boolean)} with parameter false instead + */ + @Deprecated + public static void disableOnUserRequest() { + TelemetryDefinition definition = Mapbox.getTelemetry(); + if (definition != null) { + definition.setUserTelemetryRequestState(false); + } + } +} |