From d297bf10ef89e97da30e1a00dd49560e18bcb3f0 Mon Sep 17 00:00:00 2001 From: tobrun Date: Tue, 17 Jul 2018 15:05:53 +0200 Subject: [android] - modularise the sdk --- platform/android/MapboxGLAndroidSDK/build.gradle | 3 +- .../java/com/mapbox/mapboxsdk/LibraryLoader.java | 6 +- .../src/main/java/com/mapbox/mapboxsdk/Mapbox.java | 41 ++- .../java/com/mapbox/mapboxsdk/ModuleProvider.java | 29 +++ .../com/mapbox/mapboxsdk/ModuleProviderImpl.java | 26 ++ .../mapboxsdk/constants/TelemetryConstants.java | 13 + .../com/mapbox/mapboxsdk/http/HTTPRequest.java | 279 --------------------- .../com/mapbox/mapboxsdk/http/HttpIdentifier.java | 36 +++ .../java/com/mapbox/mapboxsdk/http/HttpLogger.java | 35 +++ .../com/mapbox/mapboxsdk/http/HttpRequest.java | 31 +++ .../com/mapbox/mapboxsdk/http/HttpRequestUrl.java | 40 +++ .../com/mapbox/mapboxsdk/http/HttpRequestUtil.java | 19 +- .../com/mapbox/mapboxsdk/http/HttpResponder.java | 32 +++ .../mapbox/mapboxsdk/http/LocalRequestTask.java | 6 +- .../mapbox/mapboxsdk/http/NativeHttpRequest.java | 85 +++++++ .../main/java/com/mapbox/mapboxsdk/log/Logger.java | 204 +++++++++++++++ .../com/mapbox/mapboxsdk/log/LoggerDefinition.java | 134 ++++++++++ .../mapbox/mapboxsdk/maps/AnnotationManager.java | 10 +- .../mapboxsdk/maps/AttributionDialogManager.java | 11 +- .../mapbox/mapboxsdk/maps/MapGestureDetector.java | 40 ++- .../java/com/mapbox/mapboxsdk/maps/MapView.java | 16 +- .../java/com/mapbox/mapboxsdk/maps/MapboxMap.java | 11 +- .../com/mapbox/mapboxsdk/maps/NativeMapView.java | 20 +- .../java/com/mapbox/mapboxsdk/maps/Telemetry.java | 62 ++--- .../mapbox/mapboxsdk/maps/TelemetryDefinition.java | 40 +++ .../java/com/mapbox/mapboxsdk/maps/Transform.java | 10 +- .../maps/renderer/egl/EGLConfigChooser.java | 35 +-- .../textureview/TextureViewRenderThread.java | 24 +- .../mapboxsdk/module/http/HttpRequestImpl.java | 179 +++++++++++++ .../mapboxsdk/module/http/HttpRequestUtil.java | 64 +++++ .../mapboxsdk/module/telemetry/TelemetryImpl.java | 173 +++++++++++++ .../mapbox/mapboxsdk/net/ConnectivityReceiver.java | 9 +- .../mapbox/mapboxsdk/offline/OfflineManager.java | 10 +- .../mapboxsdk/snapshotter/MapSnapshotter.java | 9 +- .../com/mapbox/mapboxsdk/storage/FileSource.java | 16 +- .../mapboxsdk/style/layers/PropertyValue.java | 14 +- .../test/java/com/mapbox/mapboxsdk/MapboxTest.java | 23 +- .../android/MapboxGLAndroidSDKTestApp/build.gradle | 5 +- .../java/com/mapbox/mapboxsdk/maps/MapboxTest.java | 33 +++ .../mapboxsdk/testapp/MapboxApplication.java | 11 +- .../activity/camera/LatLngBoundsActivity.java | 3 - .../activity/maplayout/DebugModeActivity.java | 3 - .../mapboxsdk/testapp/utils/TimberLogger.java | 57 +++++ platform/android/core-files.txt | 4 + platform/android/gradle/dependencies.gradle | 1 + platform/android/gradle/gradle-checkstyle.gradle | 4 +- platform/android/src/http_file_source.cpp | 2 +- platform/android/src/jni.cpp | 4 + platform/android/src/logger.cpp | 34 +++ platform/android/src/logger.hpp | 24 ++ platform/android/src/logging_android.cpp | 31 +-- 51 files changed, 1508 insertions(+), 503 deletions(-) create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/ModuleProvider.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/ModuleProviderImpl.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/TelemetryConstants.java delete mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HTTPRequest.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HttpIdentifier.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HttpLogger.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HttpRequest.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HttpRequestUrl.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HttpResponder.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/NativeHttpRequest.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/log/Logger.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/log/LoggerDefinition.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/TelemetryDefinition.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/module/http/HttpRequestImpl.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/module/http/HttpRequestUtil.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/module/telemetry/TelemetryImpl.java create mode 100644 platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/MapboxTest.java create mode 100644 platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/TimberLogger.java create mode 100644 platform/android/src/logger.cpp create mode 100644 platform/android/src/logger.hpp diff --git a/platform/android/MapboxGLAndroidSDK/build.gradle b/platform/android/MapboxGLAndroidSDK/build.gradle index 597eddc334..e796c35cee 100644 --- a/platform/android/MapboxGLAndroidSDK/build.gradle +++ b/platform/android/MapboxGLAndroidSDK/build.gradle @@ -13,7 +13,6 @@ dependencies { implementation dependenciesList.mapboxJavaTurf implementation dependenciesList.supportAnnotations implementation dependenciesList.supportFragmentV4 - implementation dependenciesList.timber implementation dependenciesList.okhttp3 testImplementation dependenciesList.junit testImplementation dependenciesList.mockito @@ -160,4 +159,4 @@ apply from: "${rootDir}/gradle/gradle-javadoc.gradle" apply from: "${rootDir}/gradle/gradle-publish.gradle" apply from: "${rootDir}/gradle/gradle-checkstyle.gradle" apply from: "${rootDir}/gradle/gradle-tests-staticblockremover.gradle" -apply from: "${rootDir}/gradle/gradle-dependencies-graph.gradle" +apply from: "${rootDir}/gradle/gradle-dependencies-graph.gradle" \ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/LibraryLoader.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/LibraryLoader.java index 6633d5d952..ea3d053d4b 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/LibraryLoader.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/LibraryLoader.java @@ -1,6 +1,6 @@ package com.mapbox.mapboxsdk; -import timber.log.Timber; +import com.mapbox.mapboxsdk.log.Logger; /** * Loads the mapbox-gl shared library @@ -11,6 +11,8 @@ import timber.log.Timber; */ public abstract class LibraryLoader { + private static final String TAG = "Mbgl-LibraryLoader"; + private static final LibraryLoader DEFAULT = new LibraryLoader() { @Override public void load(String name) { @@ -39,7 +41,7 @@ public abstract class LibraryLoader { try { loader.load("mapbox-gl"); } catch (UnsatisfiedLinkError error) { - Timber.e(error, "Failed to load native shared library."); + Logger.e(TAG, "Failed to load native shared library.", error); } } 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 8c9cd362d3..ba632ebb20 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 @@ -9,13 +9,12 @@ import android.support.annotation.Nullable; import android.support.annotation.UiThread; import com.mapbox.mapboxsdk.constants.MapboxConstants; import com.mapbox.mapboxsdk.exceptions.MapboxConfigurationException; -import com.mapbox.mapboxsdk.maps.Telemetry; +import com.mapbox.mapboxsdk.log.Logger; +import com.mapbox.mapboxsdk.maps.TelemetryDefinition; import com.mapbox.mapboxsdk.net.ConnectivityReceiver; import com.mapbox.mapboxsdk.storage.FileSource; import com.mapbox.mapboxsdk.utils.ThreadUtils; -import timber.log.Timber; - /** * The entry point to initialize the Mapbox Android SDK. *

@@ -25,13 +24,18 @@ import timber.log.Timber; *

*/ @UiThread +@SuppressLint("StaticFieldLeak") public final class Mapbox { - @SuppressLint("StaticFieldLeak") + private static final String TAG = "Mbgl-Mapbox"; + + private static ModuleProvider moduleProvider; private static Mapbox INSTANCE; + private Context context; private String accessToken; private Boolean connected; + private TelemetryDefinition telemetry; /** * Get an instance of Mapbox. @@ -121,10 +125,33 @@ public final class Mapbox { */ private static void initializeTelemetry() { try { - Telemetry.initialize(); + INSTANCE.telemetry = getModuleProvider().obtainTelemetry(); } catch (Exception exception) { - Timber.e(exception); + Logger.e(TAG, "Error occured while initializing telemetry", exception); + } + } + + /** + * Get an instance of Telemetry if initialised + * + * @return instance of telemetry + */ + @Nullable + public static TelemetryDefinition getTelemetry() { + return INSTANCE.telemetry; + } + + /** + * Get the module provider + * + * @return moduleProvider + */ + @NonNull + public static ModuleProvider getModuleProvider() { + if (moduleProvider == null) { + moduleProvider = new ModuleProviderImpl(); } + return moduleProvider; } /** @@ -150,4 +177,4 @@ public final class Mapbox { accessToken = accessToken.trim().toLowerCase(MapboxConstants.MAPBOX_LOCALE); return accessToken.length() != 0 && (accessToken.startsWith("pk.") || accessToken.startsWith("sk.")); } -} +} \ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/ModuleProvider.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/ModuleProvider.java new file mode 100644 index 0000000000..12a10cd86e --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/ModuleProvider.java @@ -0,0 +1,29 @@ +package com.mapbox.mapboxsdk; + +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import com.mapbox.mapboxsdk.http.HttpRequest; +import com.mapbox.mapboxsdk.maps.TelemetryDefinition; + +/** + * Injects concrete instances of configurable abstractions + */ +public interface ModuleProvider { + + /** + * Create a new concrete implementation of HttpRequest. + * + * @return a new instance of an HttpRequest + */ + @NonNull + HttpRequest createHttpRequest(); + + /** + * Get the concrete implementation of TelemetryDefinition + * + * @return a single instance of Telemetry + */ + @Nullable + TelemetryDefinition obtainTelemetry(); + +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/ModuleProviderImpl.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/ModuleProviderImpl.java new file mode 100644 index 0000000000..4f36f2b888 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/ModuleProviderImpl.java @@ -0,0 +1,26 @@ +package com.mapbox.mapboxsdk; + +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import com.mapbox.mapboxsdk.http.HttpRequest; +import com.mapbox.mapboxsdk.maps.TelemetryDefinition; +import com.mapbox.mapboxsdk.module.http.HttpRequestImpl; +import com.mapbox.mapboxsdk.module.telemetry.TelemetryImpl; + +public class ModuleProviderImpl implements ModuleProvider { + + @Override + @NonNull + public HttpRequest createHttpRequest() { + return new HttpRequestImpl(); + } + + @Override + @Nullable + public TelemetryDefinition obtainTelemetry() { + // TODO remove singleton with next major release, + // this is needed to make static methods on TelemetryImpl + // backwards compatible without breaking semver + return TelemetryImpl.getInstance(); + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/TelemetryConstants.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/TelemetryConstants.java new file mode 100644 index 0000000000..31a1baea4a --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/TelemetryConstants.java @@ -0,0 +1,13 @@ +package com.mapbox.mapboxsdk.constants; + +public class TelemetryConstants { + + public static final String TWO_FINGER_TAP = "TwoFingerTap"; + public static final String DOUBLE_TAP = "DoubleTap"; + public static final String SINGLE_TAP = "SingleTap"; + public static final String PAN = "Pan"; + public static final String PINCH = "Pinch"; + public static final String ROTATION = "Rotation"; + public static final String PITCH = "Pitch"; + +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HTTPRequest.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HTTPRequest.java deleted file mode 100644 index 9e3056bf8e..0000000000 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HTTPRequest.java +++ /dev/null @@ -1,279 +0,0 @@ -package com.mapbox.mapboxsdk.http; - -import android.content.Context; -import android.content.pm.PackageInfo; -import android.os.Build; -import android.support.annotation.Keep; -import android.support.annotation.NonNull; -import android.text.TextUtils; -import android.util.Log; -import com.mapbox.android.telemetry.TelemetryUtils; -import com.mapbox.mapboxsdk.BuildConfig; -import com.mapbox.mapboxsdk.Mapbox; -import com.mapbox.mapboxsdk.constants.MapboxConstants; -import okhttp3.Call; -import okhttp3.Callback; -import okhttp3.Dispatcher; -import okhttp3.HttpUrl; -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.Response; -import okhttp3.ResponseBody; -import timber.log.Timber; - -import javax.net.ssl.SSLException; -import java.io.IOException; -import java.io.InterruptedIOException; -import java.net.NoRouteToHostException; -import java.net.ProtocolException; -import java.net.SocketException; -import java.net.UnknownHostException; -import java.util.concurrent.locks.ReentrantLock; - -import static android.util.Log.DEBUG; -import static android.util.Log.ERROR; -import static android.util.Log.INFO; -import static android.util.Log.VERBOSE; -import static android.util.Log.WARN; - -class HTTPRequest implements Callback { - - private static final int CONNECTION_ERROR = 0; - private static final int TEMPORARY_ERROR = 1; - private static final int PERMANENT_ERROR = 2; - - private static OkHttpClient client = new OkHttpClient.Builder().dispatcher(getDispatcher()).build(); - private static boolean logEnabled = true; - private static boolean logRequestUrl = false; - - // Reentrancy is not needed, but "Lock" is an abstract class. - private ReentrantLock lock = new ReentrantLock(); - private String userAgentString; - @Keep - private long nativePtr = 0; - private Call call; - - @Keep - private HTTPRequest(long nativePtr, String resourceUrl, String etag, String modified) { - this.nativePtr = nativePtr; - - if (resourceUrl.startsWith("local://")) { - // used by render test to serve files from assets - executeLocalRequest(resourceUrl); - return; - } - executeRequest(resourceUrl, etag, modified); - } - - @Keep - public void cancel() { - // call can be null if the constructor gets aborted (e.g, under a NoRouteToHostException). - if (call != null) { - call.cancel(); - } - - // TODO: We need a lock here because we can try - // to cancel at the same time the request is getting - // answered on the OkHTTP thread. We could get rid of - // this lock by using Runnable when we move Android - // implementation of mbgl::RunLoop to Looper. - lock.lock(); - nativePtr = 0; - lock.unlock(); - } - - @Override - public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException { - if (response.isSuccessful()) { - log(VERBOSE, String.format("[HTTP] Request was successful (code = %s).", response.code())); - } else { - // We don't want to call this unsuccessful because a 304 isn't really an error - String message = !TextUtils.isEmpty(response.message()) ? response.message() : "No additional information"; - log(DEBUG, String.format("[HTTP] Request with response code = %s: %s", response.code(), message)); - } - - ResponseBody responseBody = response.body(); - if (responseBody == null) { - log(ERROR, "[HTTP] Received empty response body"); - return; - } - - byte[] body; - try { - body = responseBody.bytes(); - } catch (IOException ioException) { - onFailure(call, ioException); - // throw ioException; - return; - } finally { - response.close(); - } - - lock.lock(); - if (nativePtr != 0) { - nativeOnResponse(response.code(), - response.header("ETag"), - response.header("Last-Modified"), - response.header("Cache-Control"), - response.header("Expires"), - response.header("Retry-After"), - response.header("x-rate-limit-reset"), - body); - } - lock.unlock(); - } - - @Override - public void onFailure(@NonNull Call call, @NonNull IOException e) { - handleFailure(call, e); - } - - static void enableLog(boolean enabled) { - logEnabled = enabled; - } - - static void enablePrintRequestUrlOnFailure(boolean enabled) { - logRequestUrl = enabled; - } - - static void setOKHttpClient(OkHttpClient client) { - HTTPRequest.client = client; - } - - private static Dispatcher getDispatcher() { - Dispatcher dispatcher = new Dispatcher(); - // Matches core limit set on - // https://github.com/mapbox/mapbox-gl-native/blob/master/platform/android/src/http_file_source.cpp#L192 - dispatcher.setMaxRequestsPerHost(20); - return dispatcher; - } - - private void executeRequest(String resourceUrl, String etag, String modified) { - try { - HttpUrl httpUrl = HttpUrl.parse(resourceUrl); - if (httpUrl == null) { - log(Log.ERROR, String.format("[HTTP] Unable to parse resourceUrl %s", resourceUrl)); - } - - final String host = httpUrl.host().toLowerCase(MapboxConstants.MAPBOX_LOCALE); - // Don't try a request to remote server if we aren't connected - if (!Mapbox.isConnected() && !host.equals("127.0.0.1") && !host.equals("localhost")) { - throw new NoRouteToHostException("No Internet connection available."); - } - - if (host.equals("mapbox.com") || host.endsWith(".mapbox.com") || host.equals("mapbox.cn") - || host.endsWith(".mapbox.cn")) { - if (httpUrl.querySize() == 0) { - resourceUrl = resourceUrl + "?"; - } else { - resourceUrl = resourceUrl + "&"; - } - resourceUrl = resourceUrl + "events=true"; - } - - Request.Builder builder = new Request.Builder() - .url(resourceUrl) - .tag(resourceUrl.toLowerCase(MapboxConstants.MAPBOX_LOCALE)) - .addHeader("User-Agent", getUserAgent()); - if (etag.length() > 0) { - builder = builder.addHeader("If-None-Match", etag); - } else if (modified.length() > 0) { - builder = builder.addHeader("If-Modified-Since", modified); - } - Request request = builder.build(); - call = client.newCall(request); - call.enqueue(this); - } catch (Exception exception) { - handleFailure(call, exception); - } - } - - private void executeLocalRequest(String resourceUrl) { - new LocalRequestTask(new LocalRequestTask.OnLocalRequestResponse() { - @Override - public void onResponse(byte[] bytes) { - if (bytes != null) { - lock.lock(); - if (nativePtr != 0) { - nativeOnResponse(200, null, null, null, null, null, null, bytes); - } - lock.unlock(); - } - } - }).execute(resourceUrl); - } - - private void handleFailure(Call call, Exception e) { - String errorMessage = e.getMessage() != null ? e.getMessage() : "Error processing the request"; - int type = getFailureType(e); - - if (logEnabled && call != null && call.request() != null) { - String requestUrl = call.request().url().toString(); - logFailure(type, errorMessage, requestUrl); - } - - lock.lock(); - if (nativePtr != 0) { - nativeOnFailure(type, errorMessage); - } - lock.unlock(); - } - - private int getFailureType(Exception e) { - if ((e instanceof NoRouteToHostException) || (e instanceof UnknownHostException) || (e instanceof SocketException) - || (e instanceof ProtocolException) || (e instanceof SSLException)) { - return CONNECTION_ERROR; - } else if ((e instanceof InterruptedIOException)) { - return TEMPORARY_ERROR; - } - return PERMANENT_ERROR; - } - - private void log(int type, String errorMessage) { - if (logEnabled) { - Timber.log(type, errorMessage); - } - } - - private void logFailure(int type, String errorMessage, String requestUrl) { - log(type == TEMPORARY_ERROR ? DEBUG : type == CONNECTION_ERROR ? INFO : WARN, - String.format( - "Request failed due to a %s error: %s %s", - type == TEMPORARY_ERROR ? "temporary" : type == CONNECTION_ERROR ? "connection" : "permanent", - errorMessage, - logRequestUrl ? requestUrl : "" - ) - ); - } - - private String getUserAgent() { - if (userAgentString == null) { - userAgentString = TelemetryUtils.toHumanReadableAscii( - String.format("%s %s (%s) Android/%s (%s)", - getApplicationIdentifier(), - BuildConfig.MAPBOX_VERSION_STRING, - BuildConfig.GIT_REVISION_SHORT, - Build.VERSION.SDK_INT, - Build.CPU_ABI) - ); - } - return userAgentString; - } - - private String getApplicationIdentifier() { - try { - Context context = Mapbox.getApplicationContext(); - PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0); - return String.format("%s/%s (%s)", context.getPackageName(), packageInfo.versionName, packageInfo.versionCode); - } catch (Exception exception) { - return ""; - } - } - - @Keep - private native void nativeOnFailure(int type, String message); - - @Keep - private native void nativeOnResponse(int code, String etag, String modified, String cacheControl, String expires, - String retryAfter, String xRateLimitReset, byte[] body); -} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HttpIdentifier.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HttpIdentifier.java new file mode 100644 index 0000000000..d50be55878 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HttpIdentifier.java @@ -0,0 +1,36 @@ +package com.mapbox.mapboxsdk.http; + +import android.content.Context; +import android.content.pm.PackageInfo; +import android.support.annotation.NonNull; +import com.mapbox.mapboxsdk.Mapbox; + +public class HttpIdentifier { + + private HttpIdentifier() { + } + + /** + * Returns the application identifier, consisting out the package name, version name and version code. + * + * @return the application identifier + */ + public static String getIdentifier() { + return getIdentifier(Mapbox.getApplicationContext()); + } + + /** + * Returns the application identifier, consisting out the package name, version name and version code. + * + * @param context the context used to retrieve the package manager from + * @return the application identifier + */ + private static String getIdentifier(@NonNull Context context) { + try { + PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0); + return String.format("%s/%s (%s)", context.getPackageName(), packageInfo.versionName, packageInfo.versionCode); + } catch (Exception exception) { + return ""; + } + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HttpLogger.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HttpLogger.java new file mode 100644 index 0000000000..2f44694f0c --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HttpLogger.java @@ -0,0 +1,35 @@ +package com.mapbox.mapboxsdk.http; + +import android.util.Log; +import com.mapbox.mapboxsdk.log.Logger; + +import static com.mapbox.mapboxsdk.http.HttpRequest.CONNECTION_ERROR; +import static com.mapbox.mapboxsdk.http.HttpRequest.TEMPORARY_ERROR; + +public class HttpLogger { + + private static final String TAG = "Mbgl-HttpRequest"; + + public static boolean logRequestUrl; + public static boolean logEnabled = true; + + private HttpLogger(){ + } + + public static void logFailure(int type, String errorMessage, String requestUrl) { + log(type == TEMPORARY_ERROR ? Log.DEBUG : type == CONNECTION_ERROR ? Log.INFO : Log.WARN, + String.format( + "Request failed due to a %s error: %s %s", + type == TEMPORARY_ERROR ? "temporary" : type == CONNECTION_ERROR ? "connection" : "permanent", + errorMessage, + logRequestUrl ? requestUrl : "" + ) + ); + } + + public static void log(int type, String errorMessage) { + if (logEnabled) { + Logger.log(type, TAG, errorMessage); + } + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HttpRequest.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HttpRequest.java new file mode 100644 index 0000000000..fdbb589fef --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HttpRequest.java @@ -0,0 +1,31 @@ +package com.mapbox.mapboxsdk.http; + +/** + * Interface definition for performing http requests. + *

+ * This allows to provide alternative implementations for the http interaction of this library. + *

+ */ +public interface HttpRequest { + + int CONNECTION_ERROR = 0; + int TEMPORARY_ERROR = 1; + int PERMANENT_ERROR = 2; + + /** + * Executes the request. + * + * @param httpRequest callback to be invoked when we receive a response + * @param nativePtr the pointer associated to the request + * @param resourceUrl the resource url to download + * @param etag http header, identifier for a specific version of a resource + * @param modified http header, used to determine if a resource hasn't been modified since + */ + void executeRequest(HttpResponder httpRequest, long nativePtr, String resourceUrl, + String etag, String modified); + + /** + * Cancels the request. + */ + void cancelRequest(); +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HttpRequestUrl.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HttpRequestUrl.java new file mode 100644 index 0000000000..fde8ae4a5d --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HttpRequestUrl.java @@ -0,0 +1,40 @@ +package com.mapbox.mapboxsdk.http; + +public class HttpRequestUrl { + + private HttpRequestUrl() { + } + + /** + * Adapts a resource request url based on the host and query size. + * + * @param host the host used as endpoint + * @param resourceUrl the resource to download + * @param querySize the query size of the resource request + * @return the adapted resource url + */ + public static String buildResourceUrl(String host, String resourceUrl, int querySize) { + if (isValidMapboxEndpoint(host)) { + if (querySize == 0) { + resourceUrl = resourceUrl + "?"; + } else { + resourceUrl = resourceUrl + "&"; + } + resourceUrl = resourceUrl + "events=true"; + } + return resourceUrl; + } + + /** + * Validates if the host used as endpoint is a valid Mapbox endpoint. + * + * @param host the host used as endpoint + * @return true if a valid Mapbox endpoint + */ + private static boolean isValidMapboxEndpoint(String host) { + return host.equals("mapbox.com") + || host.endsWith(".mapbox.com") + || host.equals("mapbox.cn") + || host.endsWith(".mapbox.cn"); + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HttpRequestUtil.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HttpRequestUtil.java index 872032867a..2b85555cc7 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HttpRequestUtil.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HttpRequestUtil.java @@ -3,8 +3,11 @@ package com.mapbox.mapboxsdk.http; import okhttp3.OkHttpClient; /** - * Utility class for setting HttpRequest configurations + * Utility class for setting HttpRequest configurations. + * + * @deprecated use {@link com.mapbox.mapboxsdk.module.http.HttpRequestUtil} instead */ +@Deprecated public class HttpRequestUtil { /** @@ -14,9 +17,11 @@ public class HttpRequestUtil { *

* * @param enabled True will enable logging, false will disable + * @deprecated use {@link com.mapbox.mapboxsdk.module.http.HttpRequestUtil#setLogEnabled(boolean)} instead */ + @Deprecated public static void setLogEnabled(boolean enabled) { - HTTPRequest.enableLog(enabled); + com.mapbox.mapboxsdk.module.http.HttpRequestUtil.setLogEnabled(enabled); } /** @@ -29,18 +34,22 @@ public class HttpRequestUtil { *

* * @param enabled True will print urls, false will disable + * @deprecated use {@link com.mapbox.mapboxsdk.module.http.HttpRequestUtil#setPrintRequestUrlOnFailure(boolean)} + * instead */ + @Deprecated public static void setPrintRequestUrlOnFailure(boolean enabled) { - HTTPRequest.enablePrintRequestUrlOnFailure(enabled); + com.mapbox.mapboxsdk.module.http.HttpRequestUtil.setPrintRequestUrlOnFailure(enabled); } /** * Set the OkHttpClient used for requesting map resources. * * @param client the OkHttpClient + * @deprecated use {@link com.mapbox.mapboxsdk.module.http.HttpRequestUtil#setOkHttpClient(OkHttpClient)} instead. */ + @Deprecated public static void setOkHttpClient(OkHttpClient client) { - HTTPRequest.setOKHttpClient(client); + com.mapbox.mapboxsdk.module.http.HttpRequestUtil.setOkHttpClient(client); } - } \ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HttpResponder.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HttpResponder.java new file mode 100644 index 0000000000..a050e07c52 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HttpResponder.java @@ -0,0 +1,32 @@ +package com.mapbox.mapboxsdk.http; + +/** + * Interface definition for a callback to be invoked when either a response was returned for a requested resource or + * when an error occurred when requesting the resource. + */ +public interface HttpResponder { + + /** + * Invoked when a resource has finished. + * + * @param responseCode http response code + * @param eTag http header, identifier for a specific version of a resource + * @param lastModified http header, used to determine if a resource hasn't been modified since + * @param cacheControl http header, used to determine cache strategy of a resource + * @param expires http header, used to determine when a resource is stale + * @param retryAfter http header, used to indicate when the service is expected to be unavailable to the client + * @param xRateLimitReset http header, used to determine the remaining window before the rate limit resets + * @param body http response body, in an array of bytes representation + */ + void onResponse(int responseCode, String eTag, String lastModified, String cacheControl, String expires, + String retryAfter, String xRateLimitReset, byte[] body); + + /** + * Invoked when a resource failed to be retrieved. + * + * @param type the error type, either one of {@link HttpRequest#CONNECTION_ERROR}, + * {@link HttpRequest#TEMPORARY_ERROR} or {@link HttpRequest#PERMANENT_ERROR} + * @param errorMessage the error message associated with the failure + */ + void handleFailure(int type, String errorMessage); +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/LocalRequestTask.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/LocalRequestTask.java index 8f31364c39..b8ed407417 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/LocalRequestTask.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/LocalRequestTask.java @@ -3,13 +3,15 @@ package com.mapbox.mapboxsdk.http; import android.content.res.AssetManager; import android.os.AsyncTask; import com.mapbox.mapboxsdk.Mapbox; -import timber.log.Timber; +import com.mapbox.mapboxsdk.log.Logger; import java.io.IOException; import java.io.InputStream; class LocalRequestTask extends AsyncTask { + private static final String TAG = "Mbgl-LocalRequestTask"; + private OnLocalRequestResponse requestResponse; LocalRequestTask(OnLocalRequestResponse requestResponse) { @@ -40,7 +42,7 @@ class LocalRequestTask extends AsyncTask { buffer = new byte[size]; input.read(buffer); } catch (IOException exception) { - Timber.e(exception); + Logger.e(TAG, "Load file failed", exception); } return buffer; } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/NativeHttpRequest.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/NativeHttpRequest.java new file mode 100644 index 0000000000..5535e20923 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/NativeHttpRequest.java @@ -0,0 +1,85 @@ +package com.mapbox.mapboxsdk.http; + +import android.support.annotation.Keep; +import com.mapbox.mapboxsdk.Mapbox; + +import java.util.concurrent.locks.ReentrantLock; + +public class NativeHttpRequest implements HttpResponder { + + private final HttpRequest httpRequest = Mapbox.getModuleProvider().createHttpRequest(); + + // Reentrancy is not needed, but "Lock" is an abstract class. + private final ReentrantLock lock = new ReentrantLock(); + + @Keep + private long nativePtr; + + @Keep + private NativeHttpRequest(long nativePtr, String resourceUrl, String etag, String modified) { + this.nativePtr = nativePtr; + + if (resourceUrl.startsWith("local://")) { + // used by render test to serve files from assets + executeLocalRequest(resourceUrl); + return; + } + httpRequest.executeRequest(this, nativePtr, resourceUrl, etag, modified); + } + + public void cancel() { + httpRequest.cancelRequest(); + + // TODO: We need a lock here because we can try + // to cancel at the same time the request is getting + // answered on the OkHTTP thread. We could get rid of + // this lock by using Runnable when we move Android + // implementation of mbgl::RunLoop to Looper. + lock.lock(); + nativePtr = 0; + lock.unlock(); + } + + public void onResponse(int responseCode, String etag, String lastModified, String cacheControl, String expires, + String retryAfter, String xRateLimitReset, byte[] body) { + lock.lock(); + if (nativePtr != 0) { + nativeOnResponse(responseCode, + etag, + lastModified, + cacheControl, + expires, + retryAfter, + xRateLimitReset, + body); + } + lock.unlock(); + } + + private void executeLocalRequest(String resourceUrl) { + new LocalRequestTask(bytes -> { + if (bytes != null) { + lock.lock(); + if (nativePtr != 0) { + nativeOnResponse(200, null, null, null, null, null, null, bytes); + } + lock.unlock(); + } + }).execute(resourceUrl); + } + + public void handleFailure(int type, String errorMessage) { + lock.lock(); + if (nativePtr != 0) { + nativeOnFailure(type, errorMessage); + } + lock.unlock(); + } + + @Keep + private native void nativeOnFailure(int type, String message); + + @Keep + private native void nativeOnResponse(int code, String etag, String modified, String cacheControl, String expires, + String retryAfter, String xRateLimitReset, byte[] body); +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/log/Logger.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/log/Logger.java new file mode 100644 index 0000000000..c5b5eec393 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/log/Logger.java @@ -0,0 +1,204 @@ +package com.mapbox.mapboxsdk.log; + +import android.util.Log; + +/** + * Logger for the Mapbox Maps SDK for Android + *

+ * 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 { + private static final String TAG = "Mbgl-PropertyValue"; + public final String name; public final T value; @@ -59,7 +59,7 @@ public class PropertyValue { if (isExpression()) { return Expression.Converter.convert((JsonArray) value); } else { - Timber.w("not a expression, try value"); + Logger.w(TAG, "not a expression, try value"); return null; } } @@ -84,7 +84,7 @@ public class PropertyValue { // noinspection unchecked return value; } else { - Timber.w("not a value, try function"); + Logger.w(TAG, "not a value, try function"); return null; } } @@ -98,14 +98,14 @@ public class PropertyValue { @Nullable public Integer getColorInt() { if (!isValue() || !(value instanceof String)) { - Timber.e("%s is not a String value and can not be converted to a color it", name); + Logger.e(TAG, String.format("%s is not a String value and can not be converted to a color it", name)); return null; } try { return ColorUtils.rgbaToColor((String) value); } catch (ConversionException ex) { - Timber.e("%s could not be converted to a Color int: %s", name, ex.getMessage()); + Logger.e(TAG, String.format("%s could not be converted to a Color int: %s", name, ex.getMessage())); return null; } } diff --git a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/MapboxTest.java b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/MapboxTest.java index 7ddab4c49d..cbb80c9c4d 100644 --- a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/MapboxTest.java +++ b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/MapboxTest.java @@ -1,8 +1,7 @@ package com.mapbox.mapboxsdk; import android.content.Context; -import android.net.ConnectivityManager; -import android.net.NetworkInfo; + import org.junit.Before; import org.junit.Test; @@ -38,7 +37,7 @@ public class MapboxTest { @Test public void testApplicationContext() { - injectMapboxSingleton("dummy"); + injectMapboxSingleton("pk.0000000001"); assertNotNull(Mapbox.getApplicationContext()); assertNotEquals(context, appContext); assertEquals(appContext, appContext); @@ -71,31 +70,17 @@ public class MapboxTest { @Test public void testConnected() { - injectMapboxSingleton("dummy"); - - // test Android connectivity - ConnectivityManager connectivityManager = mock(ConnectivityManager.class); - NetworkInfo networkInfo = mock(NetworkInfo.class); - when(appContext.getSystemService(Context.CONNECTIVITY_SERVICE)).thenReturn(connectivityManager); - when(connectivityManager.getActiveNetworkInfo()).thenReturn(networkInfo); - when(networkInfo.isConnected()).thenReturn(false); - assertFalse(Mapbox.isConnected()); - when(networkInfo.isConnected()).thenReturn(true); - assertTrue(Mapbox.isConnected()); + injectMapboxSingleton("pk.0000000001"); // test manual connectivity Mapbox.setConnected(true); assertTrue(Mapbox.isConnected()); Mapbox.setConnected(false); assertFalse(Mapbox.isConnected()); - - // reset to Android connectivity - Mapbox.setConnected(null); - assertTrue(Mapbox.isConnected()); } private void injectMapboxSingleton(String accessToken) { - Mapbox mapbox = new Mapbox(appContext, accessToken); + Mapbox mapbox = new Mapbox(context, accessToken); try { Field field = Mapbox.class.getDeclaredField("INSTANCE"); field.setAccessible(true); diff --git a/platform/android/MapboxGLAndroidSDKTestApp/build.gradle b/platform/android/MapboxGLAndroidSDKTestApp/build.gradle index d21eb73382..b4709930eb 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/build.gradle +++ b/platform/android/MapboxGLAndroidSDKTestApp/build.gradle @@ -54,10 +54,9 @@ android { dependencies { implementation dependenciesList.kotlinLib - api(project(':MapboxGLAndroidSDK')) - implementation dependenciesList.mapboxJavaServices - implementation dependenciesList.mapboxJavaTurf + implementation(project(':MapboxGLAndroidSDK')) + implementation(dependenciesList.mapboxJavaTurf) implementation dependenciesList.supportAppcompatV7 implementation dependenciesList.supportRecyclerView diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/MapboxTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/MapboxTest.java new file mode 100644 index 0000000000..3648aaeebe --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/MapboxTest.java @@ -0,0 +1,33 @@ +package com.mapbox.mapboxsdk.maps; + +import com.mapbox.mapboxsdk.Mapbox; +import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest; +import com.mapbox.mapboxsdk.testapp.activity.espresso.EspressoTestActivity; +import org.junit.Test; + +import static junit.framework.Assert.assertFalse; +import static junit.framework.Assert.assertTrue; + +public class MapboxTest extends BaseActivityTest { + + @Override + protected Class getActivityClass() { + return EspressoTestActivity.class; + } + + @Test + public void testConnected() { + validateTestSetup(); + assertTrue(Mapbox.isConnected()); + + // test manual connectivity + Mapbox.setConnected(true); + assertTrue(Mapbox.isConnected()); + Mapbox.setConnected(false); + assertFalse(Mapbox.isConnected()); + + // reset to Android connectivity + Mapbox.setConnected(null); + assertTrue(Mapbox.isConnected()); + } +} \ No newline at end of file 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..d95fcf745a 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 @@ -4,7 +4,9 @@ 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.log.Logger; +import com.mapbox.mapboxsdk.maps.TelemetryDefinition; +import com.mapbox.mapboxsdk.testapp.utils.TimberLogger; import com.mapbox.mapboxsdk.testapp.utils.TokenUtils; import com.squareup.leakcanary.LeakCanary; import timber.log.Timber; @@ -47,6 +49,7 @@ public class MapboxApplication extends Application { } private void initializeLogger() { + Logger.setLoggerDefinition(new TimberLogger()); if (BuildConfig.DEBUG) { Timber.plant(new DebugTree()); } @@ -70,7 +73,11 @@ public class MapboxApplication extends Application { String accessToken = TokenUtils.getMapboxAccessToken(getApplicationContext()); validateAccessToken(accessToken); Mapbox.getInstance(getApplicationContext(), accessToken); - Telemetry.updateDebugLoggingEnabled(true); + TelemetryDefinition telemetry = Mapbox.getTelemetry(); + if (telemetry == null) { + throw new IllegalStateException("Telemetry was unavailable during test application start."); + } + telemetry.setDebugLoggingEnabled(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/utils/TimberLogger.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/TimberLogger.java new file mode 100644 index 0000000000..369e25a012 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/TimberLogger.java @@ -0,0 +1,57 @@ +package com.mapbox.mapboxsdk.testapp.utils; + +import com.mapbox.mapboxsdk.log.LoggerDefinition; +import timber.log.Timber; + +public class TimberLogger implements LoggerDefinition { + + @Override + public void v(String tag, String msg) { + Timber.tag(tag).v(msg); + } + + @Override + public void v(String tag, String msg, Throwable tr) { + Timber.tag(tag).v(tr, msg); + } + + @Override + public void d(String tag, String msg) { + Timber.tag(tag).d(msg); + } + + @Override + public void d(String tag, String msg, Throwable tr) { + Timber.tag(tag).d(tr, msg); + } + + @Override + public void i(String tag, String msg) { + Timber.tag(tag).i(msg); + } + + @Override + public void i(String tag, String msg, Throwable tr) { + Timber.tag(tag).i(tr, msg); + } + + @Override + public void w(String tag, String msg) { + Timber.tag(tag).w(msg); + } + + @Override + public void w(String tag, String msg, Throwable tr) { + Timber.tag(tag).w(tr, msg); + } + + @Override + public void e(String tag, String msg) { + Timber.tag(tag).e(msg); + } + + @Override + public void e(String tag, String msg, Throwable tr) { + Timber.tag(tag).e(tr, msg); + } +} diff --git a/platform/android/core-files.txt b/platform/android/core-files.txt index cdcffb857f..eca7529c0b 100644 --- a/platform/android/core-files.txt +++ b/platform/android/core-files.txt @@ -204,6 +204,10 @@ platform/android/src/snapshotter/map_snapshotter.hpp platform/android/src/snapshotter/map_snapshot.cpp platform/android/src/snapshotter/map_snapshot.hpp +# Logger +platform/android/src/logger.cpp +platform/android/src/logger.hpp + # Main jni bindings platform/android/src/attach_env.cpp platform/android/src/attach_env.hpp diff --git a/platform/android/gradle/dependencies.gradle b/platform/android/gradle/dependencies.gradle index 303dd2f4b4..1f773f77b0 100644 --- a/platform/android/gradle/dependencies.gradle +++ b/platform/android/gradle/dependencies.gradle @@ -47,6 +47,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/gradle/gradle-checkstyle.gradle b/platform/android/gradle/gradle-checkstyle.gradle index 41a68f90ce..8eb4baa858 100644 --- a/platform/android/gradle/gradle-checkstyle.gradle +++ b/platform/android/gradle/gradle-checkstyle.gradle @@ -18,7 +18,9 @@ task checkstyle(type: Checkstyle) { exclude '**/style/layers/PropertyFactory.java' exclude '**/style/layers/*Layer.java' exclude '**/style/light/Light.java' - exclude '**/Expression.java' // allowing single character signature as e() + exclude '**/log/LoggerDefinition.java' + exclude '**/log/Logger.java' + exclude '**/Expression.java' classpath = files() ignoreFailures = false } 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(); diff --git a/platform/android/src/jni.cpp b/platform/android/src/jni.cpp index 18b966e261..872d8bc89a 100755 --- a/platform/android/src/jni.cpp +++ b/platform/android/src/jni.cpp @@ -49,6 +49,7 @@ #include "text/collator_jni.hpp" #include "text/local_glyph_rasterizer_jni.hpp" #include "java/lang.hpp" +#include "logger.hpp" namespace mbgl { namespace android { @@ -192,6 +193,9 @@ void registerNatives(JavaVM *vm) { LocalGlyphRasterizer::registerNative(env); Locale::registerNative(env); Collator::registerNative(env); + + // Logger + Logger::registerNative(env); } } // namespace android diff --git a/platform/android/src/logger.cpp b/platform/android/src/logger.cpp new file mode 100644 index 0000000000..1cc7660716 --- /dev/null +++ b/platform/android/src/logger.cpp @@ -0,0 +1,34 @@ +#include "logger.hpp" +#include "java_types.hpp" + +namespace mbgl { +namespace android { + +void Logger::registerNative(jni::JNIEnv& env) { + _class = *jni::Class::Find(env).NewGlobalRef(env).release(); +} + +jni::Class Logger::_class; + +void Logger::log(jni::JNIEnv& env, EventSeverity severity, const std::string &msg) { + auto tag = jni::Make(env, "Mbgl"); + auto message = jni::Make(env, msg); + using Signature = void(jni::String, jni::String); + + if (severity == EventSeverity::Debug) { + auto static debug = _class.GetStaticMethod(env, "d"); + _class.Call(env, debug, tag, message); + } else if (severity == EventSeverity::Info) { + auto static info = _class.GetStaticMethod(env, "i"); + _class.Call(env, info, tag, message); + } else if(severity == EventSeverity::Warning) { + auto static warning = _class.GetStaticMethod(env, "w"); + _class.Call(env, warning, tag, message); + } else { + auto static error = _class.GetStaticMethod(env, "e"); + _class.Call(env, error, tag, message); + } +} + +} // namespace android +} // namespace mbgl \ No newline at end of file diff --git a/platform/android/src/logger.hpp b/platform/android/src/logger.hpp new file mode 100644 index 0000000000..d4805fccd8 --- /dev/null +++ b/platform/android/src/logger.hpp @@ -0,0 +1,24 @@ +#pragma once + +#include +#include +#include "bitmap.hpp" + +namespace mbgl { +namespace android { + +class Logger { +public: + static constexpr auto Name() { + return "com/mapbox/mapboxsdk/log/Logger"; + }; + static void registerNative(jni::JNIEnv&); + + static void log(jni::JNIEnv&, EventSeverity severity, const std::string &msg); + +private: + static jni::Class _class; +}; + +} // namespace android +} // namespace mbgl \ No newline at end of file diff --git a/platform/android/src/logging_android.cpp b/platform/android/src/logging_android.cpp index 2e025c059f..1301367280 100644 --- a/platform/android/src/logging_android.cpp +++ b/platform/android/src/logging_android.cpp @@ -1,34 +1,13 @@ #include -#include +#include "logger.hpp" +#include "attach_env.hpp" namespace mbgl { -namespace { - -int severityToPriority(EventSeverity severity) { - switch(severity) { - case EventSeverity::Debug: - return ANDROID_LOG_DEBUG; - - case EventSeverity::Info: - return ANDROID_LOG_INFO; - - case EventSeverity::Warning: - return ANDROID_LOG_WARN; - - case EventSeverity::Error: - return ANDROID_LOG_ERROR; - - default: - return ANDROID_LOG_VERBOSE; - } -} - -} // namespace - void Log::platformRecord(EventSeverity severity, const std::string &msg) { - __android_log_print(severityToPriority(severity), "mbgl", "%s", msg.c_str()); + auto env{ android::AttachEnv() }; + android::Logger::log(*env, severity, msg); } -} +} \ No newline at end of file -- cgit v1.2.1