summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKonstantin Käfer <mail@kkaefer.com>2017-02-17 18:04:07 +0100
committerJohn Firebaugh <john.firebaugh@gmail.com>2017-02-21 10:48:57 -0800
commit267c2eb582850050fef4e2cdb2ba49833ffadfb2 (patch)
tree951978173eb5b508f48fa821a474ec68a00ef04e
parent7f315ef5e6d38a99c990eb5b745f34505f3a0edd (diff)
downloadqtlocation-mapboxgl-267c2eb582850050fef4e2cdb2ba49833ffadfb2.tar.gz
[android] OfflineManager#setResourceTransform to allow transforming URLs prior to internet requests
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineManager.java32
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/storage/Resource.java54
-rwxr-xr-xplatform/android/src/jni.cpp50
3 files changed, 136 insertions, 0 deletions
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 d2371fcc2f..09acda792c 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
@@ -10,6 +10,7 @@ import android.support.annotation.NonNull;
import com.mapbox.mapboxsdk.Mapbox;
import com.mapbox.mapboxsdk.constants.MapboxConstants;
+import com.mapbox.mapboxsdk.storage.Resource;
import java.io.File;
@@ -81,6 +82,22 @@ public class OfflineManager {
void onError(String error);
}
+ /**
+ * This callback allows implementors to transform URLs before they are requested
+ * from the internet. This can be used add or remove custom parameters, or reroute
+ * certain requests to other servers or endpoints.
+ */
+ public interface ResourceTransformCallback {
+ /**
+ * Called whenever a URL needs to be transformed.
+ *
+ * @param kind The kind of URL to be transformed.
+ * @param offlineRegions The original URL to be transformed.
+ * @return A URL that will now be downloaded.
+ */
+ String onURL(@Resource.Kind int kind, String url);
+ }
+
/*
* Constructors
*/
@@ -265,6 +282,18 @@ public class OfflineManager {
});
}
+ /**
+ * Sets a callback for transforming URLs requested from the internet
+ * <p>
+ * The callback will be executed on the main thread once for every requested URL.
+ * </p>
+ *
+ * @param callback the callback to be invoked
+ */
+ public void setResourceTransform(@NonNull final ResourceTransformCallback callback) {
+ setResourceTransform(mDefaultFileSourcePtr, callback);
+ }
+
/*
* Changing or bypassing this limit without permission from Mapbox is prohibited
* by the Mapbox Terms of Service.
@@ -291,6 +320,9 @@ public class OfflineManager {
long defaultFileSourcePtr, OfflineRegionDefinition definition,
byte[] metadata, CreateOfflineRegionCallback callback);
+ private native void setResourceTransform(
+ long defaultFileSourcePtr, ResourceTransformCallback callback);
+
private native void setOfflineMapboxTileCountLimit(
long defaultFileSourcePtr, long limit);
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/storage/Resource.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/storage/Resource.java
new file mode 100644
index 0000000000..af98a46a9b
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/storage/Resource.java
@@ -0,0 +1,54 @@
+package com.mapbox.mapboxsdk.storage;
+
+import android.support.annotation.IntDef;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+public final class Resource {
+ // Note: Keep this in sync with include/mbgl/storage/resource.hpp
+
+ @IntDef( {UNKNOWN, STYLE, SOURCE, TILE, GLYPHS, SPRITE_IMAGE, SPRITE_JSON})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Kind {
+ }
+
+ /**
+ * Unknown type
+ */
+ public static final int UNKNOWN = 0;
+
+ /**
+ * Style sheet JSON file
+ */
+ public static final int STYLE = 1;
+
+ /**
+ * TileJSON file as specified in https://www.mapbox.com/mapbox-gl-js/style-spec/#root-sources
+ */
+ public static final int SOURCE = 2;
+
+ /**
+ * A vector or raster tile as described in the style sheet at
+ * https://www.mapbox.com/mapbox-gl-js/style-spec/#sources
+ */
+ public static final int TILE = 3;
+
+ /**
+ * Signed distance field glyphs for text rendering. These are the URLs specified in the style
+ * in https://www.mapbox.com/mapbox-gl-js/style-spec/#root-glyphs
+ */
+ public static final int GLYPHS = 4;
+
+ /**
+ * Image part of a sprite sheet. It is constructed of the prefix in
+ * https://www.mapbox.com/mapbox-gl-js/style-spec/#root-sprite and a PNG file extension.
+ */
+ public static final int SPRITE_IMAGE = 5;
+
+ /**
+ * JSON part of a sprite sheet. It is constructed of the prefix in
+ * https://www.mapbox.com/mapbox-gl-js/style-spec/#root-sprite and a JSON file extension.
+ */
+ public static final int SPRITE_JSON = 6;
+}
diff --git a/platform/android/src/jni.cpp b/platform/android/src/jni.cpp
index 54bf092539..7e4cc82122 100755
--- a/platform/android/src/jni.cpp
+++ b/platform/android/src/jni.cpp
@@ -13,6 +13,7 @@
#include "native_map_view.hpp"
#include "connectivity_listener.hpp"
#include "default_file_source.hpp"
+#include "attach_env.hpp"
#include "style/layers/layers.hpp"
#include "style/sources/sources.hpp"
@@ -138,6 +139,8 @@ jni::jfieldID* offlineRegionDefinitionPixelRatioId = nullptr;
jni::jmethodID* createOnCreateMethodId = nullptr;
jni::jmethodID* createOnErrorMethodId = nullptr;
+jni::jmethodID* transformOnURLMethodId = nullptr;
+
jni::jmethodID* updateMetadataOnUpdateMethodId = nullptr;
jni::jmethodID* updateMetadataOnErrorMethodId = nullptr;
@@ -1391,6 +1394,45 @@ void createOfflineRegion(JNIEnv *env, jni::jobject* obj, jlong defaultFileSource
});
}
+// A deleter that doesn't retain an JNIEnv handle but instead tries to attach the JVM. This means
+// it can be used on any thread to delete a global ref.
+struct GenericGlobalRefDeleter {
+ void operator()(jni::jobject* p) const {
+ if (p) {
+ auto env = AttachEnv();
+ env->DeleteGlobalRef(jni::Unwrap(p));
+ }
+ }
+};
+
+void setResourceTransform(JNIEnv *env, jni::jobject* obj, jlong defaultFileSourcePtr, jni::jobject* transformCallback) {
+ // Checks
+ assert(defaultFileSourcePtr != 0);
+
+ mbgl::DefaultFileSource *defaultFileSource = reinterpret_cast<mbgl::DefaultFileSource *>(defaultFileSourcePtr);
+ if (transformCallback) {
+ // Launch transformCallback
+ defaultFileSource->setResourceTransform([
+ // Capture the OfflineManager and ResourceTransformCallback objects as a managed global into
+ // the lambda. They are released automatically when we're setting a new ResourceTransform in
+ // a subsequent call.
+ // Note: we're converting them to shared_ptrs because this lambda is converted to a std::function,
+ // which requires copyability of its captured variables.
+ offlineManager = std::shared_ptr<jni::jobject>(jni::NewGlobalRef(*env, obj).release(), GenericGlobalRefDeleter()),
+ callback = std::shared_ptr<jni::jobject>(jni::NewGlobalRef(*env, transformCallback).release(), GenericGlobalRefDeleter()),
+ env
+ ](mbgl::Resource::Kind kind, std::string&& url_) {
+ auto url = std_string_to_jstring(env, url_);
+ url = reinterpret_cast<jni::jstring*>(jni::CallMethod<jni::jobject*>(
+ *env, callback.get(), *transformOnURLMethodId, int(kind), url));
+ return std_string_from_jstring(env, url);
+ });
+ } else {
+ // Reset the callback
+ defaultFileSource->setResourceTransform(nullptr);
+ }
+}
+
void setOfflineMapboxTileCountLimit(JNIEnv *env, jni::jobject* obj, jlong defaultFileSourcePtr, jlong limit) {
// Checks
assert(defaultFileSourcePtr != 0);
@@ -1903,6 +1945,10 @@ void registerNatives(JavaVM *vm) {
struct CreateOfflineRegionsCallback {
static constexpr auto Name() { return "com/mapbox/mapboxsdk/offline/OfflineManager$CreateOfflineRegionCallback"; }
};
+
+ struct ResourceTransformCallback {
+ static constexpr auto Name() { return "com/mapbox/mapboxsdk/offline/OfflineManager$ResourceTransformCallback"; }
+ };
};
struct OfflineRegion {
@@ -1918,6 +1964,7 @@ void registerNatives(JavaVM *vm) {
MAKE_NATIVE_METHOD(getAccessToken, "(J)Ljava/lang/String;"),
MAKE_NATIVE_METHOD(listOfflineRegions, "(JLcom/mapbox/mapboxsdk/offline/OfflineManager$ListOfflineRegionsCallback;)V"),
MAKE_NATIVE_METHOD(createOfflineRegion, "(JLcom/mapbox/mapboxsdk/offline/OfflineRegionDefinition;[BLcom/mapbox/mapboxsdk/offline/OfflineManager$CreateOfflineRegionCallback;)V"),
+ MAKE_NATIVE_METHOD(setResourceTransform, "(JLcom/mapbox/mapboxsdk/offline/OfflineManager$ResourceTransformCallback;)V"),
MAKE_NATIVE_METHOD(setOfflineMapboxTileCountLimit, "(JJ)V")
);
@@ -1929,6 +1976,9 @@ void registerNatives(JavaVM *vm) {
createOnCreateMethodId = &jni::GetMethodID(env, createOfflineRegionCallbackClass, "onCreate", "(Lcom/mapbox/mapboxsdk/offline/OfflineRegion;)V");
createOnErrorMethodId = &jni::GetMethodID(env, createOfflineRegionCallbackClass, "onError", "(Ljava/lang/String;)V");
+ jni::Class<OfflineManager::ResourceTransformCallback> resourceTransformCallbackClass = jni::Class<OfflineManager::ResourceTransformCallback>::Find(env);
+ transformOnURLMethodId = &jni::GetMethodID(env, resourceTransformCallbackClass, "onURL", "(ILjava/lang/String;)Ljava/lang/String;");
+
offlineRegionClass = &jni::FindClass(env, OfflineRegion::Name());
offlineRegionClass = jni::NewGlobalRef(env, offlineRegionClass).release();
offlineRegionConstructorId = &jni::GetMethodID(env, *offlineRegionClass, "<init>", "()V");