From d297bf10ef89e97da30e1a00dd49560e18bcb3f0 Mon Sep 17 00:00:00 2001
From: tobrun
@@ -25,13 +24,18 @@ import timber.log.Timber;
*
+ * This allows to provide alternative implementations for the http interaction of this library.
+ *
+ * Default implementation relies on {@link Log}. + * Alternative implementations can be set with {@link #setLoggerDefinition(LoggerDefinition)}. + *
+ */ +public final class Logger { + + private static final LoggerDefinition DEFAULT = new LoggerDefinition() { + + @Override + public void v(String tag, String msg) { + Log.v(tag, msg); + } + + @Override + public void v(String tag, String msg, Throwable tr) { + Log.v(tag, msg, tr); + } + + @Override + public void d(String tag, String msg) { + Log.d(tag, msg); + } + + @Override + public void d(String tag, String msg, Throwable tr) { + Log.d(tag, msg, tr); + } + + @Override + public void i(String tag, String msg) { + Log.i(tag, msg); + } + + @Override + public void i(String tag, String msg, Throwable tr) { + Log.i(tag, msg, tr); + } + + @Override + public void w(String tag, String msg) { + Log.w(tag, msg); + } + + @Override + public void w(String tag, String msg, Throwable tr) { + Log.w(tag, msg, tr); + } + + @Override + public void e(String tag, String msg) { + Log.e(tag, msg); + } + + @Override + public void e(String tag, String msg, Throwable tr) { + Log.e(tag, msg, tr); + } + }; + + private static volatile LoggerDefinition logger = DEFAULT; + + /** + * Replace the current used logger definition. + * + * @param loggerDefinition the definition of the logger + */ + public static void setLoggerDefinition(LoggerDefinition loggerDefinition) { + logger = loggerDefinition; + } + + /** + * Send a verbose log message. + * + * @param tag Used to identify the source of a log message. It usually identifies + * the class or activity where the log call occurs. + * @param msg The message you would like logged. + */ + public static void v(String tag, String msg) { + logger.v(tag, msg); + } + + /** + * Send a verbose log message and log the exception. + * + * @param tag Used to identify the source of a log message. It usually identifies + * the class or activity where the log call occurs. + * @param msg The message you would like logged. + * @param tr An exception to log + */ + public static void v(String tag, String msg, Throwable tr) { + logger.v(tag, msg, tr); + } + + /** + * Send a debug log message. + * + * @param tag Used to identify the source of a log message. It usually identifies + * the class or activity where the log call occurs. + * @param msg The message you would like logged. + */ + public static void d(String tag, String msg) { + logger.d(tag, msg); + } + + /** + * Send a debug log message and log the exception. + * + * @param tag Used to identify the source of a log message. It usually identifies + * the class or activity where the log call occurs. + * @param msg The message you would like logged. + * @param tr An exception to log + */ + public static void d(String tag, String msg, Throwable tr) { + logger.d(tag, msg, tr); + } + + /** + * Send an info log message. + * + * @param tag Used to identify the source of a log message. It usually identifies + * the class or activity where the log call occurs. + * @param msg The message you would like logged. + */ + public static void i(String tag, String msg) { + logger.i(tag, msg); + } + + /** + * Send an info log message and log the exception. + * + * @param tag Used to identify the source of a log message. It usually identifies + * the class or activity where the log call occurs. + * @param msg The message you would like logged. + * @param tr An exception to log + */ + public static void i(String tag, String msg, Throwable tr) { + logger.i(tag, msg, tr); + } + + /** + * Send a warning log message. + * + * @param tag Used to identify the source of a log message. It usually identifies + * the class or activity where the log call occurs. + * @param msg The message you would like logged. + */ + public static void w(String tag, String msg) { + logger.w(tag, msg); + } + + /** + * Send a warning log message and log the exception. + * + * @param tag Used to identify the source of a log message. It usually identifies + * the class or activity where the log call occurs. + * @param msg The message you would like logged. + * @param tr An exception to log + */ + public static void w(String tag, String msg, Throwable tr) { + logger.w(tag, msg, tr); + } + + /** + * Send an error log message. + * + * @param tag Used to identify the source of a log message. It usually identifies + * the class or activity where the log call occurs. + * @param msg The message you would like logged. + */ + public static void e(String tag, String msg) { + logger.e(tag, msg); + } + + /** + * Send an error log message and log the exception. + * + * @param tag Used to identify the source of a log message. It usually identifies + * the class or activity where the log call occurs. + * @param msg The message you would like logged. + * @param tr An exception to log + */ + public static void e(String tag, String msg, Throwable tr) { + logger.e(tag, msg, tr); + } + + /** + * Send a log message based on severity. + * + * @param severity the log severity + * @param tag Used to identify the source of a log message. It usually identifies + * the class or activity where the log call occurs. + * @param message The message you would like logged. + */ + public static void log(int severity, String tag, String message) { + LoggerDefinition.log(severity, tag, message); + } +} \ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/log/LoggerDefinition.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/log/LoggerDefinition.java new file mode 100644 index 0000000000..27de7349f8 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/log/LoggerDefinition.java @@ -0,0 +1,134 @@ +package com.mapbox.mapboxsdk.log; + +import android.util.Log; + +/** + * Definition of a logger for the Mapbox Maps SDK for Android. + */ +public interface LoggerDefinition { + + /** + * Send a verbose log message. + * + * @param tag Used to identify the source of a log message. It usually identifies + * the class or activity where the log call occurs. + * @param msg The message you would like logged. + */ + void v(String tag, String msg); + + /** + * Send a verbose log message and log the exception. + * + * @param tag Used to identify the source of a log message. It usually identifies + * the class or activity where the log call occurs. + * @param msg The message you would like logged. + * @param tr An exception to log + */ + void v(String tag, String msg, Throwable tr); + + /** + * Send a debug log message. + * + * @param tag Used to identify the source of a log message. It usually identifies + * the class or activity where the log call occurs. + * @param msg The message you would like logged. + */ + void d(String tag, String msg); + + /** + * Send a debug log message and log the exception. + * + * @param tag Used to identify the source of a log message. It usually identifies + * the class or activity where the log call occurs. + * @param msg The message you would like logged. + * @param tr An exception to log + */ + void d(String tag, String msg, Throwable tr); + + /** + * Send an info log message. + * + * @param tag Used to identify the source of a log message. It usually identifies + * the class or activity where the log call occurs. + * @param msg The message you would like logged. + */ + void i(String tag, String msg); + + /** + * Send an info log message and log the exception. + * + * @param tag Used to identify the source of a log message. It usually identifies + * the class or activity where the log call occurs. + * @param msg The message you would like logged. + * @param tr An exception to log + */ + void i(String tag, String msg, Throwable tr); + + /** + * Send a warning log message. + * + * @param tag Used to identify the source of a log message. It usually identifies + * the class or activity where the log call occurs. + * @param msg The message you would like logged. + */ + void w(String tag, String msg); + + /** + * Send a warning log message and log the exception. + * + * @param tag Used to identify the source of a log message. It usually identifies + * the class or activity where the log call occurs. + * @param msg The message you would like logged. + * @param tr An exception to log + */ + void w(String tag, String msg, Throwable tr); + + /** + * Send an error log message. + * + * @param tag Used to identify the source of a log message. It usually identifies + * the class or activity where the log call occurs. + * @param msg The message you would like logged. + */ + void e(String tag, String msg); + + /** + * Send an error log message and log the exception. + * + * @param tag Used to identify the source of a log message. It usually identifies + * the class or activity where the log call occurs. + * @param msg The message you would like logged. + * @param tr An exception to log + */ + void e(String tag, String msg, Throwable tr); + + /** + * Send a log message based on severity. + * + * @param severity the log severity + * @param tag Used to identify the source of a log message. It usually identifies + * the class or activity where the log call occurs. + * @param message The message you would like logged. + */ + static void log(int severity, String tag, String message) { + switch (severity) { + case Log.VERBOSE: + Logger.v(tag, message); + break; + case Log.DEBUG: + Logger.d(tag, message); + break; + case Log.INFO: + Logger.i(tag, message); + break; + case Log.WARN: + Logger.w(tag, message); + break; + case Log.ERROR: + Logger.e(tag, message); + break; + default: + throw new UnsupportedOperationException(); + } + } +} \ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/AnnotationManager.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/AnnotationManager.java index 549a550d01..1abf4e6b47 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/AnnotationManager.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/AnnotationManager.java @@ -8,7 +8,6 @@ import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v4.util.LongSparseArray; import android.view.View; - import com.mapbox.mapboxsdk.Mapbox; import com.mapbox.mapboxsdk.R; import com.mapbox.mapboxsdk.annotations.Annotation; @@ -21,12 +20,11 @@ import com.mapbox.mapboxsdk.annotations.Polygon; import com.mapbox.mapboxsdk.annotations.PolygonOptions; import com.mapbox.mapboxsdk.annotations.Polyline; import com.mapbox.mapboxsdk.annotations.PolylineOptions; +import com.mapbox.mapboxsdk.log.Logger; import java.util.ArrayList; import java.util.List; -import timber.log.Timber; - /** * Responsible for managing and tracking state of Annotations linked to Map. All events related to * annotations that occur on {@link MapboxMap} are forwarded to this class. @@ -40,6 +38,8 @@ import timber.log.Timber; */ class AnnotationManager { + private static final String TAG = "Mbgl-AnnotationManager"; + private static final long NO_ANNOTATION_ID = -1; private final MapView mapView; @@ -369,7 +369,9 @@ class AnnotationManager { } private void logNonAdded(Annotation annotation) { - Timber.w("Attempting to update non-added %s with value %s", annotation.getClass().getCanonicalName(), annotation); + Logger.w(TAG, String.format( + "Attempting to update non-added %s with value %s", annotation.getClass().getCanonicalName(), annotation) + ); } // diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/AttributionDialogManager.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/AttributionDialogManager.java index c2114f458e..a56e964294 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/AttributionDialogManager.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/AttributionDialogManager.java @@ -11,6 +11,7 @@ import android.support.annotation.NonNull; import android.view.View; import android.widget.ArrayAdapter; import android.widget.Toast; +import com.mapbox.mapboxsdk.Mapbox; import com.mapbox.mapboxsdk.R; import com.mapbox.mapboxsdk.attribution.Attribution; import com.mapbox.mapboxsdk.attribution.AttributionParser; @@ -99,7 +100,10 @@ public class AttributionDialogManager implements View.OnClickListener, DialogInt builder.setPositiveButton(R.string.mapbox_attributionTelemetryPositive, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { - Telemetry.enableOnUserRequest(); + TelemetryDefinition telemetry = Mapbox.getTelemetry(); + if (telemetry != null) { + telemetry.setUserTelemetryRequestState(true); + } dialog.cancel(); } }); @@ -113,7 +117,10 @@ public class AttributionDialogManager implements View.OnClickListener, DialogInt builder.setNegativeButton(R.string.mapbox_attributionTelemetryNegative, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { - Telemetry.disableOnUserRequest(); + TelemetryDefinition telemetry = Mapbox.getTelemetry(); + if (telemetry != null) { + telemetry.setUserTelemetryRequestState(false); + } dialog.cancel(); } }); 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..977afe4bd9 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 @@ -10,7 +10,6 @@ import android.support.annotation.Nullable; import android.view.InputDevice; import android.view.MotionEvent; import android.view.animation.DecelerateInterpolator; - import com.mapbox.android.gestures.AndroidGesturesManager; import com.mapbox.android.gestures.Constants; import com.mapbox.android.gestures.MoveGestureDetector; @@ -19,13 +18,11 @@ 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.Mapbox; import com.mapbox.mapboxsdk.R; import com.mapbox.mapboxsdk.camera.CameraPosition; import com.mapbox.mapboxsdk.constants.MapboxConstants; +import com.mapbox.mapboxsdk.constants.TelemetryConstants; import com.mapbox.mapboxsdk.geometry.LatLng; import com.mapbox.mapboxsdk.utils.MathUtils; @@ -346,7 +343,7 @@ final class MapGestureDetector { notifyOnMapClickListeners(tapPoint); } - sendTelemetryEvent(Telemetry.SINGLE_TAP, new PointF(motionEvent.getX(), motionEvent.getY())); + sendTelemetryEvent(TelemetryConstants.SINGLE_TAP, new PointF(motionEvent.getX(), motionEvent.getY())); return true; } @@ -377,7 +374,7 @@ final class MapGestureDetector { zoomInAnimated(zoomFocalPoint, false); - sendTelemetryEvent(Telemetry.DOUBLE_TAP, new PointF(motionEvent.getX(), motionEvent.getY())); + sendTelemetryEvent(TelemetryConstants.DOUBLE_TAP, new PointF(motionEvent.getX(), motionEvent.getY())); return true; } @@ -439,7 +436,7 @@ final class MapGestureDetector { } transform.cancelTransitions(); - sendTelemetryEvent(Telemetry.PAN, detector.getFocalPoint()); + sendTelemetryEvent(TelemetryConstants.PAN, detector.getFocalPoint()); notifyOnMoveBeginListeners(detector); return true; } @@ -504,7 +501,7 @@ final class MapGestureDetector { // setting focalPoint in #onScaleBegin() as well, because #onScale() might not get called before #onScaleEnd() setScaleFocalPoint(detector); - sendTelemetryEvent(Telemetry.PINCH, scaleFocalPoint); + sendTelemetryEvent(TelemetryConstants.PINCH, scaleFocalPoint); notifyOnScaleBeginListeners(detector); @@ -625,7 +622,7 @@ final class MapGestureDetector { // setting in #onRotateBegin() as well, because #onRotate() might not get called before #onRotateEnd() setRotateFocalPoint(detector); - sendTelemetryEvent(Telemetry.ROTATION, rotateFocalPoint); + sendTelemetryEvent(TelemetryConstants.ROTATION, rotateFocalPoint); notifyOnRotateBeginListeners(detector); @@ -742,7 +739,7 @@ final class MapGestureDetector { transform.cancelTransitions(); - sendTelemetryEvent(Telemetry.PITCH, detector.getFocalPoint()); + sendTelemetryEvent(TelemetryConstants.PITCH, detector.getFocalPoint()); // disabling move gesture during shove gesturesManager.getMoveGestureDetector().setEnabled(false); @@ -791,7 +788,7 @@ final class MapGestureDetector { transform.cancelTransitions(); cameraChangeDispatcher.onCameraMoveStarted(REASON_API_GESTURE); - sendTelemetryEvent(Telemetry.TWO_FINGER_TAP, detector.getFocalPoint()); + sendTelemetryEvent(TelemetryConstants.TWO_FINGER_TAP, detector.getFocalPoint()); PointF zoomFocalPoint; // Single finger double tap @@ -883,16 +880,15 @@ final class MapGestureDetector { } private void sendTelemetryEvent(String eventType, PointF focalPoint) { - CameraPosition cameraPosition = transform.getCameraPosition(); - 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)); + TelemetryDefinition telemetry = Mapbox.getTelemetry(); + if (telemetry != null) { + CameraPosition cameraPosition = transform.getCameraPosition(); + if (cameraPosition != null) { + double zoom = cameraPosition.zoom; + if (isZoomValid(zoom)) { + LatLng latLng = projection.fromScreenLocation(focalPoint); + telemetry.onGestureInteraction(eventType, latLng.getLatitude(), latLng.getLongitude(), zoom); + } } } } 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 d480d28f26..e10eec7ea7 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 @@ -25,11 +25,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.Mapbox; import com.mapbox.mapboxsdk.R; import com.mapbox.mapboxsdk.annotations.Annotation; import com.mapbox.mapboxsdk.annotations.MarkerViewManager; @@ -279,12 +275,10 @@ 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)); + TelemetryDefinition telemetry = Mapbox.getTelemetry(); + if (telemetry != null) { + telemetry.onAppUserTurnstileEvent(); + } } else if (savedInstanceState.getBoolean(MapboxConstants.STATE_HAS_SAVED_STATE)) { this.savedInstanceState = savedInstanceState; } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java index 45e54a3d14..1d823455b5 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java @@ -41,6 +41,7 @@ import com.mapbox.mapboxsdk.constants.MapboxConstants; import com.mapbox.mapboxsdk.constants.Style; import com.mapbox.mapboxsdk.geometry.LatLng; import com.mapbox.mapboxsdk.geometry.LatLngBounds; +import com.mapbox.mapboxsdk.log.Logger; import com.mapbox.mapboxsdk.style.expressions.Expression; import com.mapbox.mapboxsdk.style.layers.Layer; import com.mapbox.mapboxsdk.style.light.Light; @@ -49,8 +50,6 @@ import com.mapbox.mapboxsdk.style.sources.Source; import java.util.HashMap; import java.util.List; -import timber.log.Timber; - /** * The general class to interact with in the Android Mapbox SDK. It exposes the entry point for all * methods related to the MapView. You cannot instantiate {@link MapboxMap} object directly, rather, @@ -63,6 +62,8 @@ import timber.log.Timber; @UiThread public final class MapboxMap { + private static final String TAG = "Mbgl-MapboxMap"; + private final NativeMapView nativeMapView; private final UiSettings uiSettings; @@ -296,7 +297,7 @@ public final class MapboxMap { // noinspection unchecked return (T) nativeMapView.getLayer(layerId); } catch (ClassCastException exception) { - Timber.e(exception, "Layer: %s is a different type: ", layerId); + Logger.e(TAG, String.format("Layer: %s is a different type: ", layerId), exception); return null; } } @@ -408,7 +409,7 @@ public final class MapboxMap { // noinspection unchecked return (T) nativeMapView.getSource(sourceId); } catch (ClassCastException exception) { - Timber.e(exception, "Source: %s is a different type: ", sourceId); + Logger.e(TAG, String.format("Source: %s is a different type: ", sourceId), exception); return null; } } @@ -1485,7 +1486,7 @@ public final class MapboxMap { */ public void selectMarker(@NonNull Marker marker) { if (marker == null) { - Timber.w("marker was null, so just returning"); + Logger.w(TAG, "marker was null, so just returning"); return; } annotationManager.selectMarker(marker); diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java index dcd6e54cbe..d427032b01 100755 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java @@ -24,6 +24,7 @@ import com.mapbox.mapboxsdk.exceptions.CalledFromWorkerThreadException; import com.mapbox.mapboxsdk.geometry.LatLng; import com.mapbox.mapboxsdk.geometry.LatLngBounds; import com.mapbox.mapboxsdk.geometry.ProjectedMeters; +import com.mapbox.mapboxsdk.log.Logger; import com.mapbox.mapboxsdk.maps.renderer.MapRenderer; import com.mapbox.mapboxsdk.storage.FileSource; import com.mapbox.mapboxsdk.style.expressions.Expression; @@ -33,7 +34,6 @@ import com.mapbox.mapboxsdk.style.light.Light; import com.mapbox.mapboxsdk.style.sources.CannotAddSourceException; import com.mapbox.mapboxsdk.style.sources.Source; import com.mapbox.mapboxsdk.utils.BitmapUtils; -import timber.log.Timber; import java.nio.ByteBuffer; import java.util.ArrayList; @@ -46,6 +46,8 @@ import java.util.concurrent.CopyOnWriteArrayList; // Class that wraps the native methods for convenience final class NativeMapView { + private static final String TAG = "Mbgl-NativeMapView"; + //Hold a reference to prevent it from being GC'd as long as it's used on the native side private final FileSource fileSource; @@ -111,9 +113,9 @@ final class NativeMapView { // validate if map has already been destroyed if (destroyed && !TextUtils.isEmpty(callingMethod)) { - Timber.e( + Logger.e(TAG, String.format( "You're calling `%s` after the `MapView` was destroyed, were you invoking it after `onDestroy()`?", - callingMethod + callingMethod) ); } return destroyed; @@ -151,15 +153,17 @@ final class NativeMapView { if (width > 65535) { // we have seen edge cases where devices return incorrect values #6111 - Timber.e("Device returned an out of range width size, " - + "capping value at 65535 instead of %s", width); + Logger.e(TAG, String.format("Device returned an out of range width size, " + + "capping value at 65535 instead of %s", width) + ); width = 65535; } if (height > 65535) { // we have seen edge cases where devices return incorrect values #6111 - Timber.e("Device returned an out of range height size, " - + "capping value at 65535 instead of %s", height); + Logger.e(TAG, String.format("Device returned an out of range height size, " + + "capping value at 65535 instead of %s", height) + ); height = 65535; } @@ -902,7 +906,7 @@ final class NativeMapView { try { onMapChangedListener.onMapChanged(rawChange); } catch (RuntimeException err) { - Timber.e(err, "Exception in MapView.OnMapChangedListener"); + Logger.e(TAG, "Exception in MapView.OnMapChangedListener", err); } } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Telemetry.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Telemetry.java index 10c9ce9c83..833978d8fd 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Telemetry.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Telemetry.java @@ -1,42 +1,28 @@ package com.mapbox.mapboxsdk.maps; - -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.module.telemetry.TelemetryImpl; +/** + * @deprecated use {@link TelemetryImpl} instead. + */ +@Deprecated public class Telemetry { - static final String TWO_FINGER_TAP = "TwoFingerTap"; - static final String DOUBLE_TAP = "DoubleTap"; - static final String SINGLE_TAP = "SingleTap"; - static final String PAN = "Pan"; - static final String PINCH = "Pinch"; - static final String ROTATION = "Rotation"; - static final String PITCH = "Pitch"; - private MapboxTelemetry telemetry; - - private Telemetry() { - telemetry = new MapboxTelemetry(Mapbox.getApplicationContext(), Mapbox.getAccessToken(), - BuildConfig.MAPBOX_EVENTS_USER_AGENT); - TelemetryEnabler.State telemetryState = TelemetryEnabler.retrieveTelemetryStateFromPreferences(); - if (TelemetryEnabler.State.ENABLED.equals(telemetryState)) { - telemetry.enable(); - } - } + @Deprecated public static void initialize() { - obtainTelemetry(); + // no-op } /** * Set the debug logging state of telemetry. * * @param debugLoggingEnabled true to enable logging + * @deprecated use {@link TelemetryImpl#updateDebugLoggingEnabled(boolean)} instead */ + @Deprecated public static void updateDebugLoggingEnabled(boolean debugLoggingEnabled) { - TelemetryHolder.INSTANCE.telemetry.updateDebugLoggingEnabled(debugLoggingEnabled); + TelemetryImpl.updateDebugLoggingEnabled(debugLoggingEnabled); } /** @@ -44,32 +30,32 @@ public class Telemetry { * * @param interval the selected session interval * @return true if rotation session id was updated + * @deprecated use {@link TelemetryImpl#setSessionIdRotationInterval(int)} instead */ + @Deprecated public static boolean updateSessionIdRotationInterval(SessionInterval interval) { - return TelemetryHolder.INSTANCE.telemetry.updateSessionIdRotationInterval(interval); + return TelemetryImpl.updateSessionIdRotationInterval(interval); } /** * Method to be called when an end-user has selected to participate in telemetry collection. + * + * @deprecated use {@link TelemetryImpl#setUserTelemetryRequestState(boolean)} + * with parameter true instead */ + @Deprecated public static void enableOnUserRequest() { - TelemetryEnabler.updateTelemetryState(TelemetryEnabler.State.ENABLED); - TelemetryHolder.INSTANCE.telemetry.enable(); + TelemetryImpl.enableOnUserRequest(); } /** * Method to be called when an end-user has selected to opt-out of telemetry collection. + * + * @deprecated use {@link TelemetryImpl#setUserTelemetryRequestState(boolean)} + * with parameter false instead */ + @Deprecated public static void disableOnUserRequest() { - Telemetry.obtainTelemetry().disable(); - TelemetryEnabler.updateTelemetryState(TelemetryEnabler.State.DISABLED); - } - - private static class TelemetryHolder { - private static final Telemetry INSTANCE = new Telemetry(); - } - - static MapboxTelemetry obtainTelemetry() { - return TelemetryHolder.INSTANCE.telemetry; + TelemetryImpl.disableOnUserRequest(); } -} +} \ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/TelemetryDefinition.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/TelemetryDefinition.java new file mode 100644 index 0000000000..6e92e48a0c --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/TelemetryDefinition.java @@ -0,0 +1,40 @@ +package com.mapbox.mapboxsdk.maps; + +/** + * Definition of TelemetryImpl collection + */ +public interface TelemetryDefinition { + + /** + * Register the app user turnstile event + */ + void onAppUserTurnstileEvent(); + + /** + * 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 + */ + void onGestureInteraction(String eventType, double latitude, double longitude, double zoom); + + /** + * Set the end-user selected state to participate or opt-out in telemetry collection. + */ + void setUserTelemetryRequestState(boolean enabled); + + /** + * Set the end-user selected state to participate or opt-out in telemetry collection. + */ + void setDebugLoggingEnabled(boolean debugLoggingEnabled); + + /** + * Set the telemetry rotation session id interval + * + * @param interval the selected session interval + * @return true if rotation session id was updated + */ + boolean setSessionIdRotationInterval(int interval); +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Transform.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Transform.java index c827e5e636..3c039d3de2 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Transform.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Transform.java @@ -5,15 +5,13 @@ import android.os.Handler; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.annotation.UiThread; - import com.mapbox.mapboxsdk.annotations.MarkerViewManager; import com.mapbox.mapboxsdk.camera.CameraPosition; import com.mapbox.mapboxsdk.camera.CameraUpdate; import com.mapbox.mapboxsdk.camera.CameraUpdateFactory; import com.mapbox.mapboxsdk.constants.MapboxConstants; import com.mapbox.mapboxsdk.geometry.LatLng; - -import timber.log.Timber; +import com.mapbox.mapboxsdk.log.Logger; import static com.mapbox.mapboxsdk.maps.MapView.REGION_DID_CHANGE_ANIMATED; import static com.mapbox.mapboxsdk.maps.MapboxMap.OnCameraMoveStartedListener; @@ -27,6 +25,8 @@ import static com.mapbox.mapboxsdk.maps.MapboxMap.OnCameraMoveStartedListener; */ final class Transform implements MapView.OnMapChangedListener { + private static final String TAG = "Mbgl-Transform"; + private final NativeMapView mapView; private final MarkerViewManager markerViewManager; private final Handler handler = new Handler(); @@ -339,7 +339,7 @@ final class Transform implements MapView.OnMapChangedListener { void setMinZoom(double minZoom) { if ((minZoom < MapboxConstants.MINIMUM_ZOOM) || (minZoom > MapboxConstants.MAXIMUM_ZOOM)) { - Timber.e("Not setting minZoomPreference, value is in unsupported range: %s", minZoom); + Logger.e(TAG, String.format("Not setting minZoomPreference, value is in unsupported range: %s", minZoom)); return; } mapView.setMinZoom(minZoom); @@ -351,7 +351,7 @@ final class Transform implements MapView.OnMapChangedListener { void setMaxZoom(double maxZoom) { if ((maxZoom < MapboxConstants.MINIMUM_ZOOM) || (maxZoom > MapboxConstants.MAXIMUM_ZOOM)) { - Timber.e("Not setting maxZoomPreference, value is in unsupported range: %s", maxZoom); + Logger.e(TAG, String.format("Not setting maxZoomPreference, value is in unsupported range: %s", maxZoom)); return; } mapView.setMaxZoom(maxZoom); diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/egl/EGLConfigChooser.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/egl/EGLConfigChooser.java index 46238ee789..cc29166b36 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/egl/EGLConfigChooser.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/egl/EGLConfigChooser.java @@ -3,16 +3,15 @@ package com.mapbox.mapboxsdk.maps.renderer.egl; import android.opengl.GLSurfaceView; import android.os.Build; import android.support.annotation.NonNull; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; +import com.mapbox.mapboxsdk.constants.MapboxConstants; +import com.mapbox.mapboxsdk.log.Logger; import javax.microedition.khronos.egl.EGL10; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.egl.EGLDisplay; - -import timber.log.Timber; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; import static com.mapbox.mapboxsdk.utils.Compare.compare; import static javax.microedition.khronos.egl.EGL10.EGL_ALPHA_MASK_SIZE; @@ -38,6 +37,8 @@ import static javax.microedition.khronos.egl.EGL10.EGL_WINDOW_BIT; */ public class EGLConfigChooser implements GLSurfaceView.EGLConfigChooser { + private static final String TAG = "Mbgl-EGLConfigChooser"; + /** * Requires API level 17 * @@ -72,7 +73,7 @@ public class EGLConfigChooser implements GLSurfaceView.EGLConfigChooser { // Determine number of possible configurations int[] numConfigs = getNumberOfConfigurations(egl, display, configAttribs); if (numConfigs[0] < 1) { - Timber.e("eglChooseConfig() returned no configs."); + Logger.e(TAG, "eglChooseConfig() returned no configs."); throw new EGLConfigException("eglChooseConfig() failed"); } @@ -82,7 +83,7 @@ public class EGLConfigChooser implements GLSurfaceView.EGLConfigChooser { // Choose best match EGLConfig config = chooseBestMatchConfig(egl, display, possibleConfigurations); if (config == null) { - Timber.e("No config chosen"); + Logger.e(TAG, "No config chosen"); throw new EGLConfigException("No config chosen"); } @@ -92,7 +93,9 @@ public class EGLConfigChooser implements GLSurfaceView.EGLConfigChooser { private int[] getNumberOfConfigurations(EGL10 egl, EGLDisplay display, int[] configAttributes) { int[] numConfigs = new int[1]; if (!egl.eglChooseConfig(display, configAttributes, null, 0, numConfigs)) { - Timber.e("eglChooseConfig(NULL) returned error %d", egl.eglGetError()); + Logger.e(TAG, String.format( + MapboxConstants.MAPBOX_LOCALE, "eglChooseConfig(NULL) returned error %d", egl.eglGetError()) + ); throw new EGLConfigException("eglChooseConfig() failed"); } return numConfigs; @@ -102,7 +105,9 @@ public class EGLConfigChooser implements GLSurfaceView.EGLConfigChooser { int[] configAttributes, int[] numConfigs) { EGLConfig[] configs = new EGLConfig[numConfigs[0]]; if (!egl.eglChooseConfig(display, configAttributes, configs, numConfigs[0], numConfigs)) { - Timber.e("eglChooseConfig() returned error %d", egl.eglGetError()); + Logger.e(TAG, String.format( + MapboxConstants.MAPBOX_LOCALE, "eglChooseConfig() returned error %d", egl.eglGetError()) + ); throw new EGLConfigException("eglChooseConfig() failed"); } return configs; @@ -254,11 +259,11 @@ public class EGLConfigChooser implements GLSurfaceView.EGLConfigChooser { Config bestMatch = matches.get(0); if (bestMatch.isCaveat) { - Timber.w("Chosen config has a caveat."); + Logger.w(TAG, "Chosen config has a caveat."); } if (bestMatch.isNotConformant) { - Timber.w("Chosen config is not conformant."); + Logger.w(TAG, "Chosen config is not conformant."); } return bestMatch.config; @@ -267,7 +272,9 @@ public class EGLConfigChooser implements GLSurfaceView.EGLConfigChooser { private int getConfigAttr(EGL10 egl, EGLDisplay display, EGLConfig config, int attributeName) { int[] attributevalue = new int[1]; if (!egl.eglGetConfigAttrib(display, config, attributeName, attributevalue)) { - Timber.e("eglGetConfigAttrib(%d) returned error %d", attributeName, egl.eglGetError()); + Logger.e(TAG, String.format( + MapboxConstants.MAPBOX_LOCALE, "eglGetConfigAttrib(%d) returned error %d", attributeName, egl.eglGetError()) + ); throw new EGLConfigException("eglGetConfigAttrib() failed"); } return attributevalue[0]; @@ -275,7 +282,7 @@ public class EGLConfigChooser implements GLSurfaceView.EGLConfigChooser { private int[] getConfigAttributes() { boolean emulator = inEmulator() || inGenymotion(); - Timber.i("In emulator: %s", emulator); + Logger.i(TAG, String.format("In emulator: %s", emulator)); // Get all configs at least RGB 565 with 16 depth and 8 stencil return new int[] { diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/textureview/TextureViewRenderThread.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/textureview/TextureViewRenderThread.java index 4bba160993..8f4f1c852c 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/textureview/TextureViewRenderThread.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/textureview/TextureViewRenderThread.java @@ -4,11 +4,9 @@ import android.graphics.SurfaceTexture; import android.support.annotation.NonNull; import android.support.annotation.UiThread; import android.view.TextureView; +import com.mapbox.mapboxsdk.log.Logger; import com.mapbox.mapboxsdk.maps.renderer.egl.EGLConfigChooser; -import java.lang.ref.WeakReference; -import java.util.ArrayList; - import javax.microedition.khronos.egl.EGL10; import javax.microedition.khronos.egl.EGL11; import javax.microedition.khronos.egl.EGLConfig; @@ -16,8 +14,8 @@ import javax.microedition.khronos.egl.EGLContext; import javax.microedition.khronos.egl.EGLDisplay; import javax.microedition.khronos.egl.EGLSurface; import javax.microedition.khronos.opengles.GL10; - -import timber.log.Timber; +import java.lang.ref.WeakReference; +import java.util.ArrayList; /** * The render thread is responsible for managing the communication between the @@ -26,6 +24,8 @@ import timber.log.Timber; */ class TextureViewRenderThread extends Thread implements TextureView.SurfaceTextureListener { + private static final String TAG = "Mbgl-TextureViewRenderThread"; + private final TextureViewMapRenderer mapRenderer; private final EGLHolder eglHolder; @@ -286,7 +286,7 @@ class TextureViewRenderThread extends Thread implements TextureView.SurfaceTextu case EGL10.EGL_SUCCESS: break; case EGL11.EGL_CONTEXT_LOST: - Timber.w("Context lost. Waiting for re-aquire"); + Logger.w(TAG, "Context lost. Waiting for re-aquire"); synchronized (lock) { surface = null; destroySurface = true; @@ -294,7 +294,7 @@ class TextureViewRenderThread extends Thread implements TextureView.SurfaceTextu } break; default: - Timber.w("eglSwapBuffer error: %s. Waiting or new surface", swapError); + Logger.w(TAG, String.format("eglSwapBuffer error: %s. Waiting or new surface", swapError)); // Probably lost the surface. Clear the current one and // wait for a new one to be set synchronized (lock) { @@ -390,7 +390,7 @@ class TextureViewRenderThread extends Thread implements TextureView.SurfaceTextu if (eglSurface == null || eglSurface == EGL10.EGL_NO_SURFACE) { int error = egl.eglGetError(); if (error == EGL10.EGL_BAD_NATIVE_WINDOW) { - Timber.e("createWindowSurface returned EGL_BAD_NATIVE_WINDOW."); + Logger.e(TAG, "createWindowSurface returned EGL_BAD_NATIVE_WINDOW."); } return false; } @@ -402,7 +402,7 @@ class TextureViewRenderThread extends Thread implements TextureView.SurfaceTextu if (!egl.eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext)) { // Could not make the context current, probably because the underlying // SurfaceView surface has been destroyed. - Timber.w("eglMakeCurrent: %s", egl.eglGetError()); + Logger.w(TAG, String.format("eglMakeCurrent: %s", egl.eglGetError())); return false; } @@ -422,7 +422,7 @@ class TextureViewRenderThread extends Thread implements TextureView.SurfaceTextu } if (!egl.eglDestroySurface(eglDisplay, eglSurface)) { - Timber.w("Could not destroy egl surface. Display %s, Surface %s", eglDisplay, eglSurface); + Logger.w(TAG, String.format("Could not destroy egl surface. Display %s, Surface %s", eglDisplay, eglSurface)); } eglSurface = EGL10.EGL_NO_SURFACE; @@ -434,7 +434,7 @@ class TextureViewRenderThread extends Thread implements TextureView.SurfaceTextu } if (!egl.eglDestroyContext(eglDisplay, eglContext)) { - Timber.w("Could not destroy egl context. Display %s, Context %s", eglDisplay, eglContext); + Logger.w(TAG, String.format("Could not destroy egl context. Display %s, Context %s", eglDisplay, eglContext)); } eglContext = EGL10.EGL_NO_CONTEXT; @@ -446,7 +446,7 @@ class TextureViewRenderThread extends Thread implements TextureView.SurfaceTextu } if (!egl.eglTerminate(eglDisplay)) { - Timber.w("Could not terminate egl. Display %s", eglDisplay); + Logger.w(TAG, String.format("Could not terminate egl. Display %s", eglDisplay)); } eglDisplay = EGL10.EGL_NO_DISPLAY; } 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. + *+ * 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/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); + } + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/net/ConnectivityReceiver.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/net/ConnectivityReceiver.java index 817dcdb438..08be617560 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/net/ConnectivityReceiver.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/net/ConnectivityReceiver.java @@ -9,19 +9,20 @@ import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.support.annotation.NonNull; import android.support.annotation.UiThread; - import com.mapbox.mapboxsdk.Mapbox; +import com.mapbox.mapboxsdk.log.Logger; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; -import timber.log.Timber; - /** * Interface definition for a callback to be invoked when connectivity changes. * Not public api. */ public class ConnectivityReceiver extends BroadcastReceiver { + + private static final String TAG = "Mbgl-ConnectivityReceiver"; + @SuppressLint("StaticFieldLeak") private static ConnectivityReceiver INSTANCE; @@ -84,7 +85,7 @@ public class ConnectivityReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { boolean connected = isConnected(context); - Timber.v("Connected: %s", connected); + Logger.v(TAG, String.format("Connected: %s", connected)); // Loop over listeners for (ConnectivityListener listener : listeners) { diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineManager.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineManager.java index f6dd7ff7a1..b91c4e6b36 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineManager.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineManager.java @@ -6,23 +6,23 @@ import android.os.Handler; import android.os.Looper; import android.support.annotation.Keep; import android.support.annotation.NonNull; - import com.mapbox.mapboxsdk.LibraryLoader; import com.mapbox.mapboxsdk.R; import com.mapbox.mapboxsdk.geometry.LatLngBounds; +import com.mapbox.mapboxsdk.log.Logger; import com.mapbox.mapboxsdk.net.ConnectivityReceiver; import com.mapbox.mapboxsdk.storage.FileSource; import java.io.File; -import timber.log.Timber; - /** * The offline manager is the main entry point for offline-related functionality. * It'll help you list and create offline regions. */ public class OfflineManager { + private static final String TAG = "Mbgl - OfflineManager"; + // // Static methods // @@ -113,10 +113,10 @@ public class OfflineManager { File file = new File(path); if (file.exists()) { file.delete(); - Timber.d("Old ambient cache database deleted to save space: %s", path); + Logger.d(TAG, String.format("Old ambient cache database deleted to save space: %s", path)); } } catch (Exception exception) { - Timber.e(exception, "Failed to delete old ambient cache database: "); + Logger.e(TAG, "Failed to delete old ambient cache database: ", exception); } } }).start(); diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/snapshotter/MapSnapshotter.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/snapshotter/MapSnapshotter.java index 354a8fb6cd..fac6a75742 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/snapshotter/MapSnapshotter.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/snapshotter/MapSnapshotter.java @@ -24,9 +24,9 @@ import com.mapbox.mapboxsdk.attribution.AttributionParser; import com.mapbox.mapboxsdk.camera.CameraPosition; import com.mapbox.mapboxsdk.constants.Style; import com.mapbox.mapboxsdk.geometry.LatLngBounds; +import com.mapbox.mapboxsdk.log.Logger; import com.mapbox.mapboxsdk.storage.FileSource; import com.mapbox.mapboxsdk.utils.ThreadUtils; -import timber.log.Timber; /** * The map snapshotter creates a large of the map, rendered @@ -36,6 +36,8 @@ import timber.log.Timber; @UiThread public class MapSnapshotter { + private static final String TAG = "Mbgl-MapSnapshotter"; + /** * Get notified on snapshot completion. * @@ -357,9 +359,10 @@ public class MapSnapshotter { drawAttribution(canvas, measure, anchorPoint); } else { Bitmap snapshot = mapSnapshot.getBitmap(); - Timber.e("Could not generate attribution for snapshot size: %s x %s." + Logger.e(TAG, String.format("Could not generate attribution for snapshot size: %s x %s." + " You are required to provide your own attribution for the used sources: %s", - snapshot.getWidth(), snapshot.getHeight(), mapSnapshot.getAttributions()); + snapshot.getWidth(), snapshot.getHeight(), mapSnapshot.getAttributions()) + ); } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/storage/FileSource.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/storage/FileSource.java index 495e425976..590a9f2862 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/storage/FileSource.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/storage/FileSource.java @@ -9,7 +9,6 @@ import android.os.Environment; import android.support.annotation.Keep; import android.support.annotation.NonNull; import android.support.annotation.UiThread; - import com.mapbox.mapboxsdk.Mapbox; import com.mapbox.mapboxsdk.constants.MapboxConstants; import com.mapbox.mapboxsdk.utils.ThreadUtils; @@ -17,7 +16,7 @@ import com.mapbox.mapboxsdk.utils.ThreadUtils; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; -import timber.log.Timber; +import com.mapbox.mapboxsdk.log.Logger; /** * Holds a central reference to the core's DefaultFileSource for as long as @@ -25,10 +24,11 @@ import timber.log.Timber; */ public class FileSource { - private static String resourcesCachePath; - private static String internalCachePath; + private static final String TAG = "Mbgl-FileSource"; private static final Lock resourcesCachePathLoaderLock = new ReentrantLock(); private static final Lock internalCachePathLoaderLock = new ReentrantLock(); + private static String resourcesCachePath; + private static String internalCachePath; /** * This callback allows implementors to transform URLs before they are requested @@ -87,9 +87,9 @@ public class FileSource { MapboxConstants.KEY_META_DATA_SET_STORAGE_EXTERNAL, MapboxConstants.DEFAULT_SET_STORAGE_EXTERNAL); } catch (PackageManager.NameNotFoundException exception) { - Timber.e(exception, "Failed to read the package metadata: "); + Logger.e(TAG, "Failed to read the package metadata: ", exception); } catch (Exception exception) { - Timber.e(exception, "Failed to read the storage key: "); + Logger.e(TAG, "Failed to read the storage key: ", exception); } String cachePath = null; @@ -98,7 +98,7 @@ public class FileSource { // Try getting the external storage path cachePath = context.getExternalFilesDir(null).getAbsolutePath(); } catch (NullPointerException exception) { - Timber.e(exception, "Failed to obtain the external storage path: "); + Logger.e(TAG, "Failed to obtain the external storage path: ", exception); } } @@ -126,7 +126,7 @@ public class FileSource { return true; } - Timber.w("External storage was requested but it isn't readable. For API level < 18" + Logger.w(TAG, "External storage was requested but it isn't readable. For API level < 18" + " make sure you've requested READ_EXTERNAL_STORAGE or WRITE_EXTERNAL_STORAGE" + " permissions in your app Manifest (defaulting to internal storage)."); diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyValue.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyValue.java index fa1779a6c7..a38f810f1c 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyValue.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyValue.java @@ -3,19 +3,19 @@ package com.mapbox.mapboxsdk.style.layers; import android.support.annotation.ColorInt; import android.support.annotation.NonNull; import android.support.annotation.Nullable; - import com.google.gson.JsonArray; import com.mapbox.mapboxsdk.exceptions.ConversionException; +import com.mapbox.mapboxsdk.log.Logger; import com.mapbox.mapboxsdk.style.expressions.Expression; import com.mapbox.mapboxsdk.utils.ColorUtils; -import timber.log.Timber; - /** * Properties for Layer */ public class PropertyValue