diff options
author | Ivo van Dongen <info@ivovandongen.nl> | 2017-02-16 16:16:47 +0200 |
---|---|---|
committer | Ivo van Dongen <ivovandongen@users.noreply.github.com> | 2017-02-24 17:54:20 +0200 |
commit | 465c949153a838bb3159204ab268eb551fbd2e6c (patch) | |
tree | 250922b879261580b1252a78b461218be9012bc0 /platform/android/src/offline | |
parent | 7d9018093a61d327fa7ca1312845d2a00d928380 (diff) | |
download | qtlocation-mapboxgl-465c949153a838bb3159204ab268eb551fbd2e6c.tar.gz |
[android] jni high level binding refactor
Diffstat (limited to 'platform/android/src/offline')
-rw-r--r-- | platform/android/src/offline/offline_manager.cpp | 164 | ||||
-rw-r--r-- | platform/android/src/offline/offline_manager.hpp | 75 | ||||
-rw-r--r-- | platform/android/src/offline/offline_region.cpp | 308 | ||||
-rw-r--r-- | platform/android/src/offline/offline_region.hpp | 99 | ||||
-rw-r--r-- | platform/android/src/offline/offline_region_definition.cpp | 69 | ||||
-rw-r--r-- | platform/android/src/offline/offline_region_definition.hpp | 34 | ||||
-rw-r--r-- | platform/android/src/offline/offline_region_error.cpp | 53 | ||||
-rw-r--r-- | platform/android/src/offline/offline_region_error.hpp | 21 | ||||
-rw-r--r-- | platform/android/src/offline/offline_region_status.cpp | 39 | ||||
-rw-r--r-- | platform/android/src/offline/offline_region_status.hpp | 21 |
10 files changed, 883 insertions, 0 deletions
diff --git a/platform/android/src/offline/offline_manager.cpp b/platform/android/src/offline/offline_manager.cpp new file mode 100644 index 0000000000..02871e7fdf --- /dev/null +++ b/platform/android/src/offline/offline_manager.cpp @@ -0,0 +1,164 @@ +#include "offline_manager.hpp" + +#include <mbgl/util/string.hpp> + +#include "../attach_env.hpp" +#include "../jni/generic_global_ref_deleter.hpp" + +namespace mbgl { +namespace android { + +// OfflineManager // + +OfflineManager::OfflineManager(jni::JNIEnv& env, jni::Object<FileSource> jFileSource) + : fileSource(mbgl::android::FileSource::getDefaultFileSource(env, jFileSource)) { +} + +OfflineManager::~OfflineManager() {} + +void OfflineManager::setOfflineMapboxTileCountLimit(jni::JNIEnv&, jni::jlong limit) { + fileSource.setOfflineMapboxTileCountLimit(limit); +} + +void OfflineManager::listOfflineRegions(jni::JNIEnv& env_, jni::Object<FileSource> jFileSource_, jni::Object<ListOfflineRegionsCallback> callback_) { + // list regions + fileSource.listOfflineRegions([ + //Keep a shared ptr to a global reference of the callback and file source so they are not GC'd in the meanwhile + callback = std::shared_ptr<jni::jobject>(callback_.NewGlobalRef(env_).release()->Get(), GenericGlobalRefDeleter()), + jFileSource = std::shared_ptr<jni::jobject>(jFileSource_.NewGlobalRef(env_).release()->Get(), GenericGlobalRefDeleter()) + ](std::exception_ptr error, mbgl::optional<std::vector<mbgl::OfflineRegion>> regions) mutable { + + // Reattach, the callback comes from a different thread + android::UniqueEnv env = android::AttachEnv(); + + if (error) { + OfflineManager::ListOfflineRegionsCallback::onError(*env, jni::Object<ListOfflineRegionsCallback>(*callback), error); + } else if (regions) { + OfflineManager::ListOfflineRegionsCallback::onList(*env, jni::Object<FileSource>(*jFileSource), jni::Object<ListOfflineRegionsCallback>(*callback), std::move(regions)); + } + }); +} + +void OfflineManager::createOfflineRegion(jni::JNIEnv& env_, + jni::Object<FileSource> jFileSource_, + jni::Object<OfflineRegionDefinition> definition_, + jni::Array<jni::jbyte> metadata_, + jni::Object<CreateOfflineRegionCallback> callback_) { + // Convert + + // XXX hardcoded cast for now as we only support OfflineTilePyramidRegionDefinition + auto definition = OfflineTilePyramidRegionDefinition::getDefinition(env_, jni::Object<OfflineTilePyramidRegionDefinition>(*definition_)); + + mbgl::OfflineRegionMetadata metadata; + if (metadata_) { + metadata = OfflineRegion::metadata(env_, metadata_); + } + + // Create region + fileSource.createOfflineRegion(definition, metadata, [ + //Keep a shared ptr to a global reference of the callback and file source so they are not GC'd in the meanwhile + callback = std::shared_ptr<jni::jobject>(callback_.NewGlobalRef(env_).release()->Get(), GenericGlobalRefDeleter()), + jFileSource = std::shared_ptr<jni::jobject>(jFileSource_.NewGlobalRef(env_).release()->Get(), GenericGlobalRefDeleter()) + ](std::exception_ptr error, mbgl::optional<mbgl::OfflineRegion> region) mutable { + + // Reattach, the callback comes from a different thread + android::UniqueEnv env = android::AttachEnv(); + + if (error) { + OfflineManager::CreateOfflineRegionCallback::onError(*env, jni::Object<CreateOfflineRegionCallback>(*callback), error); + } else if (region) { + OfflineManager::CreateOfflineRegionCallback::onCreate( + *env, + jni::Object<FileSource>(*jFileSource), + jni::Object<CreateOfflineRegionCallback>(*callback), std::move(region) + ); + } + }); +} + +jni::Class<OfflineManager> OfflineManager::javaClass; + +void OfflineManager::registerNative(jni::JNIEnv& env) { + OfflineManager::ListOfflineRegionsCallback::registerNative(env); + OfflineManager::CreateOfflineRegionCallback::registerNative(env); + + javaClass = *jni::Class<OfflineManager>::Find(env).NewGlobalRef(env).release(); + + #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) + + jni::RegisterNativePeer<OfflineManager>( env, javaClass, "nativePtr", + std::make_unique<OfflineManager, JNIEnv&, jni::Object<FileSource>>, + "initialize", + "finalize", + METHOD(&OfflineManager::setOfflineMapboxTileCountLimit, "setOfflineMapboxTileCountLimit"), + METHOD(&OfflineManager::listOfflineRegions, "listOfflineRegions"), + METHOD(&OfflineManager::createOfflineRegion, "createOfflineRegion")); +} + +// OfflineManager::ListOfflineRegionsCallback // + +void OfflineManager::ListOfflineRegionsCallback::onError(jni::JNIEnv& env, + jni::Object<OfflineManager::ListOfflineRegionsCallback> callback, + std::exception_ptr error) { + static auto method = javaClass.GetMethod<void (jni::String)>(env, "onError"); + std::string message = mbgl::util::toString(error); + callback.Call(env, method, jni::Make<jni::String>(env, message)); +} + +void OfflineManager::ListOfflineRegionsCallback::onList(jni::JNIEnv& env, + jni::Object<FileSource> jFileSource, + jni::Object<OfflineManager::ListOfflineRegionsCallback> callback, + mbgl::optional<std::vector<mbgl::OfflineRegion>> regions) { + //Convert the regions to java peer objects + std::size_t index = 0; + auto jregions = jni::Array<jni::Object<OfflineRegion>>::New(env, regions->size(), OfflineRegion::javaClass); + for (auto& region : *regions) { + auto jregion = OfflineRegion::New(env, jFileSource, std::move(region)); + jregions.Set(env, index, jregion); + jni::DeleteLocalRef(env, jregion); + index++; + } + + // Trigger callback + static auto method = javaClass.GetMethod<void (jni::Array<jni::Object<OfflineRegion>>)>(env, "onList"); + callback.Call(env, method, jregions); + jni::DeleteLocalRef(env, jregions); +} + +jni::Class<OfflineManager::ListOfflineRegionsCallback> OfflineManager::ListOfflineRegionsCallback::javaClass; + +void OfflineManager::ListOfflineRegionsCallback::registerNative(jni::JNIEnv& env) { + javaClass = *jni::Class<OfflineManager::ListOfflineRegionsCallback>::Find(env).NewGlobalRef(env).release(); +} + +// OfflineManager::CreateOfflineRegionCallback // + +void OfflineManager::CreateOfflineRegionCallback::onError(jni::JNIEnv& env, + jni::Object<OfflineManager::CreateOfflineRegionCallback> callback, + std::exception_ptr error) { + static auto method = javaClass.GetMethod<void (jni::String)>(env, "onError"); + std::string message = mbgl::util::toString(error); + callback.Call(env, method, jni::Make<jni::String>(env, message)); +} + +void OfflineManager::CreateOfflineRegionCallback::onCreate(jni::JNIEnv& env, + jni::Object<FileSource> jFileSource, + jni::Object<OfflineManager::CreateOfflineRegionCallback> callback, + mbgl::optional<mbgl::OfflineRegion> region) { + //Convert the region to java peer object + auto jregion = OfflineRegion::New(env, jFileSource, std::move(*region)); + + // Trigger callback + static auto method = javaClass.GetMethod<void (jni::Object<OfflineRegion>)>(env, "onCreate"); + callback.Call(env, method, jregion); + jni::DeleteLocalRef(env, jregion); +} + +jni::Class<OfflineManager::CreateOfflineRegionCallback> OfflineManager::CreateOfflineRegionCallback::javaClass; + +void OfflineManager::CreateOfflineRegionCallback::registerNative(jni::JNIEnv& env) { + javaClass = *jni::Class<OfflineManager::CreateOfflineRegionCallback>::Find(env).NewGlobalRef(env).release(); +} + +} // namespace android +} // namespace mbgl diff --git a/platform/android/src/offline/offline_manager.hpp b/platform/android/src/offline/offline_manager.hpp new file mode 100644 index 0000000000..9ae2714ca2 --- /dev/null +++ b/platform/android/src/offline/offline_manager.hpp @@ -0,0 +1,75 @@ +#pragma once + + +#include <mbgl/storage/default_file_source.hpp> +#include <mbgl/storage/offline.hpp> +#include <jni/jni.hpp> + +#include "../file_source.hpp" +#include "offline_region.hpp" +#include "offline_region_definition.hpp" + + +namespace mbgl { +namespace android { + +class OfflineManager { +public: + + class ListOfflineRegionsCallback { + public: + static constexpr auto Name() { return "com/mapbox/mapboxsdk/offline/OfflineManager$ListOfflineRegionsCallback";} + + static void onError(jni::JNIEnv&, jni::Object<OfflineManager::ListOfflineRegionsCallback>, std::exception_ptr); + + static void onList(jni::JNIEnv&, + jni::Object<FileSource>, + jni::Object<OfflineManager::ListOfflineRegionsCallback>, + mbgl::optional<std::vector<mbgl::OfflineRegion>>); + + static jni::Class<OfflineManager::ListOfflineRegionsCallback> javaClass; + + static void registerNative(jni::JNIEnv&); + }; + + class CreateOfflineRegionCallback { + public: + static constexpr auto Name() { return "com/mapbox/mapboxsdk/offline/OfflineManager$CreateOfflineRegionCallback"; } + + static void onError(jni::JNIEnv&, jni::Object<OfflineManager::CreateOfflineRegionCallback>, std::exception_ptr); + + static void onCreate(jni::JNIEnv&, + jni::Object<FileSource>, + jni::Object<OfflineManager::CreateOfflineRegionCallback>, + mbgl::optional<mbgl::OfflineRegion>); + + static jni::Class<OfflineManager::CreateOfflineRegionCallback> javaClass; + + static void registerNative(jni::JNIEnv&); + }; + + static constexpr auto Name() { return "com/mapbox/mapboxsdk/offline/OfflineManager"; }; + + static jni::Class<OfflineManager> javaClass; + + static void registerNative(jni::JNIEnv&); + + OfflineManager(jni::JNIEnv&, jni::Object<FileSource>); + ~OfflineManager(); + + void setOfflineMapboxTileCountLimit(jni::JNIEnv&, jni::jlong limit); + + void listOfflineRegions(jni::JNIEnv&, jni::Object<FileSource>, jni::Object<ListOfflineRegionsCallback> callback); + + void createOfflineRegion(jni::JNIEnv&, + jni::Object<FileSource> jFileSource_, + jni::Object<OfflineRegionDefinition> definition, + jni::Array<jni::jbyte> metadata, + jni::Object<OfflineManager::CreateOfflineRegionCallback> callback); + +private: + mbgl::DefaultFileSource& fileSource; +}; + +} // namespace android +} // namespace mbgl diff --git a/platform/android/src/offline/offline_region.cpp b/platform/android/src/offline/offline_region.cpp new file mode 100644 index 0000000000..856434d266 --- /dev/null +++ b/platform/android/src/offline/offline_region.cpp @@ -0,0 +1,308 @@ +#include "offline_region.hpp" + +#include <mbgl/util/logging.hpp> +#include <mbgl/util/string.hpp> + +#include "offline_region_definition.hpp" +#include "offline_region_error.hpp" +#include "offline_region_status.hpp" +#include "../attach_env.hpp" +#include "../jni/generic_global_ref_deleter.hpp" + +namespace mbgl { +namespace android { + +// OfflineRegion // + +OfflineRegion::OfflineRegion(jni::JNIEnv& env, jni::jlong offlineRegionPtr, jni::Object<FileSource> jFileSource) + : region(reinterpret_cast<mbgl::OfflineRegion *>(offlineRegionPtr)), + fileSource(mbgl::android::FileSource::getDefaultFileSource(env, jFileSource)) {} + +OfflineRegion::~OfflineRegion() {} + +void OfflineRegion::setOfflineRegionObserver(jni::JNIEnv& env_, jni::Object<OfflineRegion::OfflineRegionObserver> callback) { + + // Define the observer + class Observer : public mbgl::OfflineRegionObserver { + public: + Observer(jni::UniqueObject<OfflineRegion::OfflineRegionObserver>&& callback_) + //TODO add a generic deleter for jni::Object + : callback(callback_.release()->Get()) { + } + + ~Observer() override { + android::UniqueEnv env = android::AttachEnv(); + env->DeleteGlobalRef(Unwrap(*callback)); + } + + void statusChanged(mbgl::OfflineRegionStatus status) override { + // Reattach, the callback comes from a different thread + android::UniqueEnv env = android::AttachEnv(); + + // Status object + auto jStatus = OfflineRegionStatus::New(*env, status); + + // Call + static auto method = OfflineRegion::OfflineRegionObserver::javaClass + .GetMethod<void (jni::Object<OfflineRegionStatus>)>(*env, "onStatusChanged"); + callback.Call(*env, method, jStatus); + + // Delete references + jni::DeleteLocalRef(*env, jStatus); + } + + void responseError(mbgl::Response::Error error) override { + // Reattach, the callback comes from a different thread + android::UniqueEnv env = android::AttachEnv(); + + // Error object + auto jError = OfflineRegionError::New(*env, error); + + // Call + static auto method = OfflineRegion::OfflineRegionObserver::javaClass + .GetMethod<void (jni::Object<mbgl::android::OfflineRegionError>)>(*env, "onError"); + callback.Call(*env, method, jError); + + // Delete references + jni::DeleteLocalRef(*env, jError); + } + + void mapboxTileCountLimitExceeded(uint64_t limit) override { + // Reattach, the callback comes from a different thread + android::UniqueEnv env = android::AttachEnv(); + + // Send limit + static auto method = OfflineRegion::OfflineRegionObserver::javaClass + .GetMethod<void (jni::jlong)>(*env, "mapboxTileCountLimitExceeded"); + callback.Call(*env, method, jlong(limit)); + } + + jni::Object<OfflineRegion::OfflineRegionObserver> callback; + }; + + // Set the observer + fileSource.setOfflineRegionObserver(*region, std::make_unique<Observer>(callback.NewGlobalRef(env_))); +} + +void OfflineRegion::setOfflineRegionDownloadState(jni::JNIEnv&, jni::jint jState) { + // State + mbgl::OfflineRegionDownloadState state; + switch (jState) { + case 0: + state = mbgl::OfflineRegionDownloadState::Inactive; + break; + case 1: + state = mbgl::OfflineRegionDownloadState::Active; + break; + default: + mbgl::Log::Error(mbgl::Event::JNI, "State can only be 0 (inactive) or 1 (active)."); + return; + } + + fileSource.setOfflineRegionDownloadState(*region, state); +} + +void OfflineRegion::getOfflineRegionStatus(jni::JNIEnv& env_, jni::Object<OfflineRegionStatusCallback> callback_) { + + fileSource.getOfflineRegionStatus(*region, [ + //Ensure the object is not gc'd in the meanwhile + callback = std::shared_ptr<jni::jobject>(callback_.NewGlobalRef(env_).release()->Get(), GenericGlobalRefDeleter()) + ](std::exception_ptr error, mbgl::optional<mbgl::OfflineRegionStatus> status) mutable { + // Reattach, the callback comes from a different thread + android::UniqueEnv env = android::AttachEnv(); + + if (error) { + OfflineRegionStatusCallback::onError(*env, jni::Object<OfflineRegionStatusCallback>(*callback), error); + } else if (status) { + OfflineRegionStatusCallback::onStatus(*env, jni::Object<OfflineRegionStatusCallback>(*callback), std::move(status)); + } + }); +} + +void OfflineRegion::deleteOfflineRegion(jni::JNIEnv& env_, jni::Object<OfflineRegionDeleteCallback> callback_) { + // Delete + fileSource.deleteOfflineRegion(std::move(*region), [ + //Ensure the object is not gc'd in the meanwhile + callback = std::shared_ptr<jni::jobject>(callback_.NewGlobalRef(env_).release()->Get(), GenericGlobalRefDeleter()) + ](std::exception_ptr error) mutable { + // Reattach, the callback comes from a different thread + android::UniqueEnv env = android::AttachEnv(); + + if (error) { + OfflineRegionDeleteCallback::onError(*env, jni::Object<OfflineRegionDeleteCallback>(*callback), error); + } else { + OfflineRegionDeleteCallback::onDelete(*env, jni::Object<OfflineRegionDeleteCallback>(*callback)); + } + }); +} + +void OfflineRegion::updateOfflineRegionMetadata(jni::JNIEnv& env_, jni::Array<jni::jbyte> jMetadata, jni::Object<OfflineRegionUpdateMetadataCallback> callback_) { + + // Convert + auto metadata = OfflineRegion::metadata(env_, jMetadata); + + fileSource.updateOfflineMetadata(region->getID(), metadata, [ + //Ensure the object is not gc'd in the meanwhile + callback = std::shared_ptr<jni::jobject>(callback_.NewGlobalRef(env_).release()->Get(), GenericGlobalRefDeleter()) + ](std::exception_ptr error, mbgl::optional<mbgl::OfflineRegionMetadata> data) mutable { + // Reattach, the callback comes from a different thread + android::UniqueEnv env = android::AttachEnv(); + + if (error) { + OfflineRegionUpdateMetadataCallback::onError(*env, jni::Object<OfflineRegionUpdateMetadataCallback>(*callback), error); + } else if (data) { + OfflineRegionUpdateMetadataCallback::onUpdate(*env, jni::Object<OfflineRegionUpdateMetadataCallback>(*callback), std::move(data)); + } + }); +} + +jni::Object<OfflineRegion> OfflineRegion::New(jni::JNIEnv& env, jni::Object<FileSource> jFileSource, mbgl::OfflineRegion region) { + + // Definition + auto definition = jni::Object<OfflineRegionDefinition>(*OfflineTilePyramidRegionDefinition::New(env, region.getDefinition())); + + // Metadata + auto metadata = OfflineRegion::metadata(env, region.getMetadata()); + + // Create region java object + static auto constructor = OfflineRegion::javaClass.GetConstructor<jni::jlong, jni::Object<FileSource>, jni::jlong, jni::Object<OfflineRegionDefinition>, jni::Array<jni::jbyte>>(env); + auto jregion = OfflineRegion::javaClass.New(env, constructor, + reinterpret_cast<jni::jlong>(new mbgl::OfflineRegion(std::move(region))), //Copy a region to the heap + jFileSource, jni::jlong(region.getID()), definition, metadata); + + //Delete references + jni::DeleteLocalRef(env, definition); + jni::DeleteLocalRef(env, metadata); + + return jregion; +} + +jni::Array<jni::jbyte> OfflineRegion::metadata(jni::JNIEnv& env, mbgl::OfflineRegionMetadata metadata_) { + std::vector<jni::jbyte> convertedMetadata(metadata_.begin(), metadata_.end()); + std::size_t length = static_cast<std::size_t>(convertedMetadata.size()); + auto metadata = jni::Array<jni::jbyte>::New(env, length); + metadata.SetRegion<std::vector<jni::jbyte>>(env, 0, convertedMetadata); + return metadata; +} + +mbgl::OfflineRegionMetadata OfflineRegion::metadata(jni::JNIEnv& env, jni::Array<jni::jbyte> metadata_) { + std::size_t length = metadata_.Length(env); + auto metadata_tmp = std::vector<jni::jbyte>(); + metadata_tmp.resize(length); + metadata_.GetRegion<std::vector<jni::jbyte>>(env, 0, metadata_tmp); + auto metadata = std::vector<uint8_t>(metadata_tmp.begin(), metadata_tmp.end()); + return metadata; +} + +jni::Class<OfflineRegion> OfflineRegion::javaClass; + +void OfflineRegion::registerNative(jni::JNIEnv& env) { + OfflineRegion::OfflineRegionObserver::registerNative(env); + OfflineRegion::OfflineRegionStatusCallback::registerNative(env); + OfflineRegion::OfflineRegionDeleteCallback::registerNative(env); + OfflineRegion::OfflineRegionUpdateMetadataCallback::registerNative(env); + + javaClass = *jni::Class<OfflineRegion>::Find(env).NewGlobalRef(env).release(); + + #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) + + jni::RegisterNativePeer<OfflineRegion>( env, javaClass, "nativePtr", + std::make_unique<OfflineRegion, JNIEnv&, jni::jlong, jni::Object<FileSource>>, + "initialize", + "finalize", + METHOD(&OfflineRegion::setOfflineRegionObserver, "setOfflineRegionObserver"), + METHOD(&OfflineRegion::setOfflineRegionDownloadState, "setOfflineRegionDownloadState"), + METHOD(&OfflineRegion::getOfflineRegionStatus, "getOfflineRegionStatus"), + METHOD(&OfflineRegion::deleteOfflineRegion, "deleteOfflineRegion"), + METHOD(&OfflineRegion::updateOfflineRegionMetadata, "updateOfflineRegionMetadata") + ); +} + +// OfflineRegionObserver // + +jni::Class<OfflineRegion::OfflineRegionObserver> OfflineRegion::OfflineRegionObserver::javaClass; + +void OfflineRegion::OfflineRegionObserver::registerNative(jni::JNIEnv& env) { + javaClass = *jni::Class<OfflineRegion::OfflineRegionObserver>::Find(env).NewGlobalRef(env).release(); +} + +// OfflineRegionStatusCallback // + +jni::Class<OfflineRegion::OfflineRegionStatusCallback> OfflineRegion::OfflineRegionStatusCallback::javaClass; + +void OfflineRegion::OfflineRegionStatusCallback::registerNative(jni::JNIEnv& env) { + javaClass = *jni::Class<OfflineRegionStatusCallback>::Find(env).NewGlobalRef(env).release(); +} + +void OfflineRegion::OfflineRegionStatusCallback::onError(jni::JNIEnv& env, + jni::Object<OfflineRegion::OfflineRegionStatusCallback> callback, + std::exception_ptr error) { + static auto method = javaClass.GetMethod<void (jni::String)>(env, "onError"); + std::string message = mbgl::util::toString(error); + callback.Call(env, method, jni::Make<jni::String>(env, message)); +} + +void OfflineRegion::OfflineRegionStatusCallback::onStatus(jni::JNIEnv& env, + jni::Object<OfflineRegion::OfflineRegionStatusCallback> callback, + mbgl::optional<mbgl::OfflineRegionStatus> status) { + //Convert to java peer object + auto jStatus = OfflineRegionStatus::New(env, std::move(*status)); + + // Trigger callback + static auto method = javaClass.GetMethod<void (jni::Object<OfflineRegionStatus>)>(env, "onStatus"); + callback.Call(env, method, jStatus); + jni::DeleteLocalRef(env, jStatus); +} + +// OfflineRegionDeleteCallback // + +jni::Class<OfflineRegion::OfflineRegionDeleteCallback> OfflineRegion::OfflineRegionDeleteCallback::javaClass; + +void OfflineRegion::OfflineRegionDeleteCallback::registerNative(jni::JNIEnv& env) { + javaClass = *jni::Class<OfflineRegionDeleteCallback>::Find(env).NewGlobalRef(env).release(); +} + +void OfflineRegion::OfflineRegionDeleteCallback::onError(jni::JNIEnv& env, + jni::Object<OfflineRegion::OfflineRegionDeleteCallback> callback, + std::exception_ptr error) { + static auto method = javaClass.GetMethod<void (jni::String)>(env, "onError"); + std::string message = mbgl::util::toString(error); + callback.Call(env, method, jni::Make<jni::String>(env, message)); +} + +void OfflineRegion::OfflineRegionDeleteCallback::onDelete(jni::JNIEnv& env, jni::Object<OfflineRegion::OfflineRegionDeleteCallback> callback) { + // Trigger callback + static auto method = javaClass.GetMethod<void ()>(env, "onDelete"); + callback.Call(env, method); +} + +// OfflineRegionUpdateMetadataCallback // + +jni::Class<OfflineRegion::OfflineRegionUpdateMetadataCallback> OfflineRegion::OfflineRegionUpdateMetadataCallback::javaClass; + +void OfflineRegion::OfflineRegionUpdateMetadataCallback::registerNative(jni::JNIEnv& env) { + javaClass = *jni::Class<OfflineRegionUpdateMetadataCallback>::Find(env).NewGlobalRef(env).release(); +} + +void OfflineRegion::OfflineRegionUpdateMetadataCallback::onError(jni::JNIEnv& env, + jni::Object<OfflineRegion::OfflineRegionUpdateMetadataCallback> callback, + std::exception_ptr error) { + static auto method = javaClass.GetMethod<void (jni::String)>(env, "onError"); + std::string message = mbgl::util::toString(error); + callback.Call(env, method, jni::Make<jni::String>(env, message)); +} + +void OfflineRegion::OfflineRegionUpdateMetadataCallback::onUpdate(jni::JNIEnv& env, + jni::Object<OfflineRegion::OfflineRegionUpdateMetadataCallback> callback, + mbgl::optional<mbgl::OfflineRegionMetadata> metadata) { + //Convert to java peer object + auto jMetadata = OfflineRegion::metadata(env, std::move(*metadata)); + + // Trigger callback + static auto method = javaClass.GetMethod<void (jni::Array<jni::jbyte>)>(env, "onUpdate"); + callback.Call(env, method, jMetadata); + jni::DeleteLocalRef(env, jMetadata); +} + +} // namespace android +} // namespace mbgl diff --git a/platform/android/src/offline/offline_region.hpp b/platform/android/src/offline/offline_region.hpp new file mode 100644 index 0000000000..c05383a91a --- /dev/null +++ b/platform/android/src/offline/offline_region.hpp @@ -0,0 +1,99 @@ +#pragma once + +#include <mbgl/storage/offline.hpp> +#include <jni/jni.hpp> + +#include "../file_source.hpp" + +#include <memory> + +namespace mbgl { +namespace android { + +class OfflineRegion { +public: + class OfflineRegionObserver { + public: + static constexpr auto Name() { return "com/mapbox/mapboxsdk/offline/OfflineRegion$OfflineRegionObserver"; }; + + static jni::Class<OfflineRegionObserver> javaClass; + + static void registerNative(jni::JNIEnv&); + }; + + class OfflineRegionStatusCallback { + public: + static constexpr auto Name() { return "com/mapbox/mapboxsdk/offline/OfflineRegion$OfflineRegionStatusCallback"; }; + + static void onError(jni::JNIEnv&, jni::Object<OfflineRegionStatusCallback>, std::exception_ptr); + + static void onStatus(jni::JNIEnv&, + jni::Object<OfflineRegionStatusCallback>, + mbgl::optional<mbgl::OfflineRegionStatus>); + + static jni::Class<OfflineRegionStatusCallback> javaClass; + + static void registerNative(jni::JNIEnv&); + }; + + class OfflineRegionDeleteCallback { + public: + static constexpr auto Name() { return "com/mapbox/mapboxsdk/offline/OfflineRegion$OfflineRegionDeleteCallback"; }; + + static void onError(jni::JNIEnv&, jni::Object<OfflineRegionDeleteCallback>, std::exception_ptr); + + static void onDelete(jni::JNIEnv&, jni::Object<OfflineRegionDeleteCallback>); + + static jni::Class<OfflineRegionDeleteCallback> javaClass; + + static void registerNative(jni::JNIEnv&); + }; + + class OfflineRegionUpdateMetadataCallback { + public: + static constexpr auto Name() { return "com/mapbox/mapboxsdk/offline/OfflineRegion$OfflineRegionUpdateMetadataCallback"; }; + + static void onError(jni::JNIEnv&, jni::Object<OfflineRegionUpdateMetadataCallback>, std::exception_ptr); + + static void onUpdate(jni::JNIEnv&, + jni::Object<OfflineRegionUpdateMetadataCallback>, + mbgl::optional<mbgl::OfflineRegionMetadata>); + + static jni::Class<OfflineRegionUpdateMetadataCallback> javaClass; + + static void registerNative(jni::JNIEnv&); + }; + + static constexpr auto Name() { return "com/mapbox/mapboxsdk/offline/OfflineRegion"; }; + + OfflineRegion(jni::JNIEnv&, jni::jlong, jni::Object<FileSource>); + + ~OfflineRegion(); + + void setOfflineRegionObserver(jni::JNIEnv&, jni::Object<OfflineRegion::OfflineRegionObserver>); + + void setOfflineRegionDownloadState(jni::JNIEnv&, jni::jint); + + void getOfflineRegionStatus(jni::JNIEnv&, jni::Object<OfflineRegion::OfflineRegionStatusCallback>); + + void deleteOfflineRegion(jni::JNIEnv&, jni::Object<OfflineRegionDeleteCallback>); + + void updateOfflineRegionMetadata(jni::JNIEnv&, jni::Array<jni::jbyte>, jni::Object<OfflineRegionUpdateMetadataCallback>); + + static jni::Object<OfflineRegion> New(jni::JNIEnv&, jni::Object<FileSource>, mbgl::OfflineRegion); + + static jni::Array<jni::jbyte> metadata(jni::JNIEnv&, mbgl::OfflineRegionMetadata); + + static mbgl::OfflineRegionMetadata metadata(jni::JNIEnv&, jni::Array<jni::jbyte>); + + static jni::Class<OfflineRegion> javaClass; + + static void registerNative(jni::JNIEnv&); + +private: + std::unique_ptr<mbgl::OfflineRegion> region; + mbgl::DefaultFileSource& fileSource; +}; + +} // namespace android +} // namespace mbgl diff --git a/platform/android/src/offline/offline_region_definition.cpp b/platform/android/src/offline/offline_region_definition.cpp new file mode 100644 index 0000000000..66a9bdf99d --- /dev/null +++ b/platform/android/src/offline/offline_region_definition.cpp @@ -0,0 +1,69 @@ +#include "offline_region_definition.hpp" + +#include "../geometry/lat_lng_bounds.hpp" + +namespace mbgl { +namespace android { + +// OfflineRegionDefinition // + +jni::Class<OfflineRegionDefinition> OfflineRegionDefinition::javaClass; + +void OfflineRegionDefinition::registerNative(jni::JNIEnv& env) { + javaClass = *jni::Class<OfflineRegionDefinition>::Find(env).NewGlobalRef(env).release(); +} + +// OfflineTilePyramidRegionDefinition // + +jni::Object<OfflineTilePyramidRegionDefinition> OfflineTilePyramidRegionDefinition::New(jni::JNIEnv& env, mbgl::OfflineTilePyramidRegionDefinition definition) { + + //Convert objects + auto styleURL = jni::Make<jni::String>(env, definition.styleURL); + auto bounds = LatLngBounds::New(env, definition.bounds); + + static auto constructor = javaClass.GetConstructor<jni::String, jni::Object<LatLngBounds>, jni::jdouble, jni::jdouble, jni::jfloat>(env); + auto jdefinition = javaClass.New(env, constructor, styleURL, bounds, definition.minZoom, definition.maxZoom, definition.pixelRatio); + + //Delete References + jni::DeleteLocalRef(env, styleURL); + jni::DeleteLocalRef(env, bounds); + + return jdefinition; +} + +mbgl::OfflineTilePyramidRegionDefinition OfflineTilePyramidRegionDefinition::getDefinition(jni::JNIEnv& env, jni::Object<OfflineTilePyramidRegionDefinition> jDefinition) { + // Field references + static auto styleURLF = javaClass.GetField<jni::String>(env, "styleURL"); + static auto boundsF = javaClass.GetField<jni::Object<LatLngBounds>>(env, "bounds"); + static auto minZoomF = javaClass.GetField<jni::jdouble>(env, "minZoom"); + static auto maxZoomF = javaClass.GetField<jni::jdouble>(env, "maxZoom"); + static auto pixelRatioF = javaClass.GetField<jni::jfloat>(env, "pixelRatio"); + + // Get objects + auto jStyleURL = jDefinition.Get(env, styleURLF); + auto jBounds = jDefinition.Get(env, boundsF); + + // Create definition + mbgl::OfflineTilePyramidRegionDefinition definition( + jni::Make<std::string>(env, jStyleURL), + LatLngBounds::getLatLngBounds(env, jBounds), + jDefinition.Get(env, minZoomF), + jDefinition.Get(env, maxZoomF), + jDefinition.Get(env, pixelRatioF) + ); + + // Delete references + jni::DeleteLocalRef(env, jStyleURL); + jni::DeleteLocalRef(env, jBounds); + + return definition; +} + +jni::Class<OfflineTilePyramidRegionDefinition> OfflineTilePyramidRegionDefinition::javaClass; + +void OfflineTilePyramidRegionDefinition::registerNative(jni::JNIEnv& env) { + javaClass = *jni::Class<OfflineTilePyramidRegionDefinition>::Find(env).NewGlobalRef(env).release(); +} + +} // namespace android +} // namespace mbgl diff --git a/platform/android/src/offline/offline_region_definition.hpp b/platform/android/src/offline/offline_region_definition.hpp new file mode 100644 index 0000000000..2ca82a4d96 --- /dev/null +++ b/platform/android/src/offline/offline_region_definition.hpp @@ -0,0 +1,34 @@ +#pragma once + +#include <mbgl/storage/offline.hpp> +#include <jni/jni.hpp> + +namespace mbgl { +namespace android { + +class OfflineRegionDefinition { +public: + static constexpr auto Name() { return "com/mapbox/mapboxsdk/offline/OfflineRegionDefinition"; }; + + static jni::Class<OfflineRegionDefinition> javaClass; + + static void registerNative(jni::JNIEnv&); + +}; + +class OfflineTilePyramidRegionDefinition: public OfflineRegionDefinition { +public: + static constexpr auto Name() { return "com/mapbox/mapboxsdk/offline/OfflineTilePyramidRegionDefinition"; }; + + static jni::Object<OfflineTilePyramidRegionDefinition> New(jni::JNIEnv&, mbgl::OfflineTilePyramidRegionDefinition); + + static mbgl::OfflineTilePyramidRegionDefinition getDefinition(jni::JNIEnv&, jni::Object<OfflineTilePyramidRegionDefinition>); + + static jni::Class<OfflineTilePyramidRegionDefinition> javaClass; + + static void registerNative(jni::JNIEnv&); + +}; + +} // namespace android +} // namespace mbgl diff --git a/platform/android/src/offline/offline_region_error.cpp b/platform/android/src/offline/offline_region_error.cpp new file mode 100644 index 0000000000..b0a19f934f --- /dev/null +++ b/platform/android/src/offline/offline_region_error.cpp @@ -0,0 +1,53 @@ +#include "offline_region_error.hpp" + +namespace mbgl { +namespace android { + +jni::Object<OfflineRegionError> OfflineRegionError::New(jni::JNIEnv& env, mbgl::Response::Error error) { + + // Handle the value of reason independently of the underlying int value + std::string reason; + switch(error.reason) { + case mbgl::Response::Error::Reason::Success: + reason = "REASON_SUCCESS"; + break; + case mbgl::Response::Error::Reason::NotFound: + reason = "REASON_NOT_FOUND"; + break; + case mbgl::Response::Error::Reason::Server: + reason = "REASON_SERVER"; + break; + case mbgl::Response::Error::Reason::Connection: + reason = "REASON_CONNECTION"; + break; + case mbgl::Response::Error::Reason::RateLimit: + reason = "REASON_RATE_LIMIT"; + break; + case mbgl::Response::Error::Reason::Other: + reason = "REASON_OTHER"; + break; + } + + // Convert + auto jReason = jni::Make<jni::String>(env, reason); + auto jMessage = jni::Make<jni::String>(env, error.message); + + // Create java object + static auto constructor = javaClass.GetConstructor<jni::String, jni::String>(env); + auto jError = javaClass.New(env, constructor, jReason, jMessage); + + // Delete references + jni::DeleteLocalRef(env, jReason); + jni::DeleteLocalRef(env, jMessage); + + return jError; +} + +jni::Class<OfflineRegionError> OfflineRegionError::javaClass; + +void OfflineRegionError::registerNative(jni::JNIEnv& env) { + javaClass = *jni::Class<OfflineRegionError>::Find(env).NewGlobalRef(env).release(); +} + +} // namespace android +} // namespace mbgl diff --git a/platform/android/src/offline/offline_region_error.hpp b/platform/android/src/offline/offline_region_error.hpp new file mode 100644 index 0000000000..61efaca67e --- /dev/null +++ b/platform/android/src/offline/offline_region_error.hpp @@ -0,0 +1,21 @@ +#pragma once + +#include <mbgl/storage/offline.hpp> +#include <jni/jni.hpp> + +namespace mbgl { +namespace android { + +class OfflineRegionError { +public: + static constexpr auto Name() { return "com/mapbox/mapboxsdk/offline/OfflineRegionError"; }; + + static jni::Object<OfflineRegionError> New(jni::JNIEnv&, mbgl::Response::Error); + + static jni::Class<OfflineRegionError> javaClass; + + static void registerNative(jni::JNIEnv&); +}; + +} // namespace android +} // namespace mbgl diff --git a/platform/android/src/offline/offline_region_status.cpp b/platform/android/src/offline/offline_region_status.cpp new file mode 100644 index 0000000000..d0bbae124f --- /dev/null +++ b/platform/android/src/offline/offline_region_status.cpp @@ -0,0 +1,39 @@ +#include "offline_region_status.hpp" + +namespace mbgl { +namespace android { + +jni::Object<OfflineRegionStatus> OfflineRegionStatus::New(jni::JNIEnv& env, mbgl::OfflineRegionStatus status) { + + // Convert to jint + jint downloadState; + switch(status.downloadState) { + case mbgl::OfflineRegionDownloadState::Inactive: + downloadState = 0; + break; + case mbgl::OfflineRegionDownloadState::Active: + downloadState = 1; + break; + } + + // Create java object + static auto constructor = javaClass.GetConstructor<jint, jlong, jlong, jlong, jlong, jlong, jboolean>(env); + return javaClass.New(env, constructor, + downloadState, + jlong(status.completedResourceCount), + jlong(status.completedResourceSize), + jlong(status.completedTileCount), + jlong(status.completedTileSize), + jlong(status.requiredResourceCount), + jboolean(status.requiredResourceCountIsPrecise) + ); +} + +jni::Class<OfflineRegionStatus> OfflineRegionStatus::javaClass; + +void OfflineRegionStatus::registerNative(jni::JNIEnv& env) { + javaClass = *jni::Class<OfflineRegionStatus>::Find(env).NewGlobalRef(env).release(); +} + +} // namespace android +} // namespace mbgl diff --git a/platform/android/src/offline/offline_region_status.hpp b/platform/android/src/offline/offline_region_status.hpp new file mode 100644 index 0000000000..b29a653655 --- /dev/null +++ b/platform/android/src/offline/offline_region_status.hpp @@ -0,0 +1,21 @@ +#pragma once + +#include <mbgl/storage/offline.hpp> +#include <jni/jni.hpp> + +namespace mbgl { +namespace android { + +class OfflineRegionStatus { +public: + static constexpr auto Name() { return "com/mapbox/mapboxsdk/offline/OfflineRegionStatus"; }; + + static jni::Object<OfflineRegionStatus> New(jni::JNIEnv&, mbgl::OfflineRegionStatus status); + + static jni::Class<OfflineRegionStatus> javaClass; + + static void registerNative(jni::JNIEnv&); +}; + +} // namespace android +} // namespace mbgl |