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 7a5b58ad948..0939608e038 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 @@ -22,7 +22,7 @@ public class OfflineManager { */ public interface ListOfflineRegionsCallback { - void onList(List offlineRegions); + void onList(OfflineRegion[] offlineRegions); void onError(String error); } diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml index 2c3751cf600..7888c2599b9 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml @@ -19,10 +19,10 @@ - - - - + + + + offlineRegions) { + public void onList(OfflineRegion[] offlineRegions) { // Stop progress bar OfflineActivity.this.endProgress("Region list completed."); // Check result - if (offlineRegions == null || offlineRegions.size() == 0) { + if (offlineRegions == null || offlineRegions.length == 0) { showMessage("You have no regions yet."); return; } diff --git a/platform/android/src/jni.cpp b/platform/android/src/jni.cpp index 5c75e071ba2..e2bb5fce67f 100755 --- a/platform/android/src/jni.cpp +++ b/platform/android/src/jni.cpp @@ -123,6 +123,7 @@ jmethodID offlineManagerClassConstructorId = nullptr; jfieldID offlineManagerClassPtrId = nullptr; jclass listOfflineRegionsCallbackClass = nullptr; +jmethodID listOnListMethodId = nullptr; jmethodID listOnErrorMethodId = nullptr; jclass offlineRegionClass = nullptr; @@ -1682,28 +1683,54 @@ void JNICALL listOfflineRegions(JNIEnv *env, jobject obj, jlong defaultFileSourc return; } + // We need to add the corresponding DeleteGlobalRef + listCallback = reinterpret_cast(env->NewGlobalRef(listCallback)); + // Launch listCallback mbgl::DefaultFileSource *defaultFileSource = reinterpret_cast(defaultFileSourcePtr); - defaultFileSource->listOfflineRegions([&env, &listCallback](std::exception_ptr error, mbgl::optional> regions) { + defaultFileSource->listOfflineRegions([defaultFileSourcePtr, listCallback](std::exception_ptr error, mbgl::optional> regions) { // Reattach, the callback comes from a different thread - jboolean renderDetach = attach_jni_thread(theJVM, &env, "Offline Thread"); + JNIEnv *env2; + jboolean renderDetach = attach_jni_thread(theJVM, &env2, "Offline Thread"); if (renderDetach) { mbgl::Log::Debug(mbgl::Event::JNI, "Attached."); } if (error) { std::string message = mbgl::util::toString(error); - env->CallVoidMethod(listCallback, listOnErrorMethodId, std_string_to_jstring(env, message)); + env2->CallVoidMethod(listCallback, listOnErrorMethodId, std_string_to_jstring(env2, message)); } else if (regions) { - for(std::vector::size_type i = 0; i != regions->size(); i++) { - /* Handle regions */ - mbgl::Log::Error(mbgl::Event::JNI, "Region."); + // Build the OfflineManager object + jobject jManager = env2->NewObject(offlineManagerClass, offlineManagerClassConstructorId); + env2->SetLongField(jManager, offlineManagerClassPtrId, defaultFileSourcePtr); + + // Build jobjectArray + jsize index = 0; + jobjectArray jRegions = env2->NewObjectArray(regions->size(), offlineRegionClass, NULL); + for (std::vector::iterator it = regions->begin(); it != regions->end(); ++it) { + // Build the Region object + jobject jRegion = env2->NewObject(offlineRegionClass, offlineRegionConstructorId); + env2->SetObjectField(jRegion, offlineRegionOfflineManagerId, jManager); + env2->SetLongField(jRegion, offlineRegionIdId, it->getID()); + + // Moves the region on the stack into a heap-allocated one + env2->SetLongField(jRegion, offlineRegionPtrId, + reinterpret_cast(new mbgl::OfflineRegion(std::move(*it)))); + + // Add element to array + env2->SetObjectArrayElement(jRegions, index, jRegion); + + // Increment index + index++; } + + // Trigger callback + env2->CallVoidMethod(listCallback, listOnListMethodId, jRegions); } // Detach when we're done - detach_jni_thread(theJVM, &env, renderDetach); + detach_jni_thread(theJVM, &env2, renderDetach); }); } @@ -1764,9 +1791,31 @@ void JNICALL createOfflineRegion(JNIEnv *env, jobject obj, jlong defaultFileSour }); } -void JNICALL setOfflineRegionObserver(JNIEnv *env, jobject obj, jobject offlineRegion, jobject observerCallback) { +void JNICALL setOfflineRegionObserver(JNIEnv *env, jobject obj, jobject offlineRegion_, jobject observerCallback) { mbgl::Log::Error(mbgl::Event::JNI, "setOfflineRegionObserver"); + // Offline region + jlong offlineRegionPtr = env->GetLongField(offlineRegion_, offlineRegionPtrId); + mbgl::OfflineRegion *offlineRegion = reinterpret_cast(offlineRegionPtr); + + // File source + jobject jManager = env->GetObjectField(offlineRegion_, offlineRegionOfflineManagerId); + jlong defaultFileSourcePtr = env->GetLongField(jManager, offlineManagerClassPtrId); + mbgl::DefaultFileSource *defaultFileSource = reinterpret_cast(defaultFileSourcePtr); + + // Define the observer + class Observer : public mbgl::OfflineRegionObserver { + void statusChanged(mbgl::OfflineRegionStatus status) override { + mbgl::Log::Error(mbgl::Event::JNI, "statusChanged"); + } + + void responseError(mbgl::Response::Error error) override { + mbgl::Log::Error(mbgl::Event::JNI, "responseError"); + } + }; + + // Set the observer + defaultFileSource->setOfflineRegionObserver(*offlineRegion, std::make_unique()); } void JNICALL setOfflineRegionDownloadState(JNIEnv *env, jobject obj, jobject offlineRegion_, jint offlineRegionDownloadState) { @@ -2228,6 +2277,12 @@ extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { return JNI_ERR; } + listOnListMethodId = env->GetMethodID(listOfflineRegionsCallbackClass, "onList", "([Lcom/mapbox/mapboxsdk/offline/OfflineRegion;)V"); + if (listOnListMethodId == nullptr) { + env->ExceptionDescribe(); + return JNI_ERR; + } + listOnErrorMethodId = env->GetMethodID(listOfflineRegionsCallbackClass, "onError", "(Ljava/lang/String;)V"); if (listOnErrorMethodId == nullptr) { env->ExceptionDescribe(); @@ -2884,6 +2939,7 @@ extern "C" JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved) { offlineManagerClassPtrId = nullptr; offlineManagerClassPtrId = nullptr; env->DeleteGlobalRef(listOfflineRegionsCallbackClass); + listOnListMethodId = nullptr; listOnErrorMethodId = nullptr; env->DeleteGlobalRef(offlineRegionClass); offlineRegionConstructorId = nullptr; diff --git a/platform/android/src/jni.hpp b/platform/android/src/jni.hpp index e19beffad10..6c3e94702ff 100644 --- a/platform/android/src/jni.hpp +++ b/platform/android/src/jni.hpp @@ -107,6 +107,7 @@ extern jclass offlineManagerClass; extern jmethodID offlineManagerClassConstructorId; extern jfieldID offlineManagerClassPtrId; extern jclass listOfflineRegionsCallbackClass; +extern jmethodID listOnListMethodId; extern jmethodID listOnErrorMethodId; extern jclass offlineRegionClass; extern jfieldID offlineRegionOfflineManagerId;