diff options
Diffstat (limited to 'platform/android/src/offline/offline_region.cpp')
-rw-r--r-- | platform/android/src/offline/offline_region.cpp | 203 |
1 files changed, 73 insertions, 130 deletions
diff --git a/platform/android/src/offline/offline_region.cpp b/platform/android/src/offline/offline_region.cpp index 5ed37eda73..1cd73a7c76 100644 --- a/platform/android/src/offline/offline_region.cpp +++ b/platform/android/src/offline/offline_region.cpp @@ -7,81 +7,62 @@ #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) +OfflineRegion::OfflineRegion(jni::JNIEnv& env, jni::jlong offlineRegionPtr, const 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) { +void OfflineRegion::setOfflineRegionObserver(jni::JNIEnv& env_, const 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)); + Observer(jni::Global<jni::Object<OfflineRegion::OfflineRegionObserver>, jni::EnvAttachingDeleter> callback_) + : callback(std::move(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); + static auto& javaClass = jni::Class<OfflineRegion::OfflineRegionObserver>::Singleton(*env); + static auto method = javaClass.GetMethod<void (jni::Object<OfflineRegionStatus>)>(*env, "onStatusChanged"); - // 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); + callback.Call(*env, method, OfflineRegionStatus::New(*env, status)); } 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); + static auto& javaClass = jni::Class<OfflineRegion::OfflineRegionObserver>::Singleton(*env); + static auto method = javaClass.GetMethod<void (jni::Object<mbgl::android::OfflineRegionError>)>(*env, "onError"); - // Delete references - jni::DeleteLocalRef(*env, jError); + callback.Call(*env, method, OfflineRegionError::New(*env, error)); } 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"); + static auto& javaClass = jni::Class<OfflineRegion::OfflineRegionObserver>::Singleton(*env); + static auto method = javaClass.GetMethod<void (jni::jlong)>(*env, "mapboxTileCountLimitExceeded"); + callback.Call(*env, method, jlong(limit)); } - jni::Object<OfflineRegion::OfflineRegionObserver> callback; + jni::Global<jni::Object<OfflineRegion::OfflineRegionObserver>, jni::EnvAttachingDeleter> callback; }; // Set the observer - fileSource.setOfflineRegionObserver(*region, std::make_unique<Observer>(callback.NewGlobalRef(env_))); + fileSource.setOfflineRegionObserver(*region, std::make_unique<Observer>(jni::NewGlobal<jni::EnvAttachingDeleter>(env_, callback))); } void OfflineRegion::setOfflineRegionDownloadState(jni::JNIEnv&, jni::jint jState) { @@ -102,89 +83,84 @@ void OfflineRegion::setOfflineRegionDownloadState(jni::JNIEnv&, jni::jint jState fileSource.setOfflineRegionDownloadState(*region, state); } -void OfflineRegion::getOfflineRegionStatus(jni::JNIEnv& env_, jni::Object<OfflineRegionStatusCallback> callback_) { +void OfflineRegion::getOfflineRegionStatus(jni::JNIEnv& env_, const jni::Object<OfflineRegionStatusCallback>& callback_) { + auto globalCallback = jni::NewGlobal<jni::EnvAttachingDeleter>(env_, 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()) + callback = std::make_shared<decltype(globalCallback)>(std::move(globalCallback)) ](mbgl::expected<mbgl::OfflineRegionStatus, std::exception_ptr> status) mutable { // Reattach, the callback comes from a different thread android::UniqueEnv env = android::AttachEnv(); if (status) { - OfflineRegionStatusCallback::onStatus(*env, jni::Object<OfflineRegionStatusCallback>(*callback), std::move(*status)); + OfflineRegionStatusCallback::onStatus(*env, *callback, std::move(*status)); } else { - OfflineRegionStatusCallback::onError(*env, jni::Object<OfflineRegionStatusCallback>(*callback), status.error()); + OfflineRegionStatusCallback::onError(*env, *callback, status.error()); } }); } -void OfflineRegion::deleteOfflineRegion(jni::JNIEnv& env_, jni::Object<OfflineRegionDeleteCallback> callback_) { - // Delete +void OfflineRegion::deleteOfflineRegion(jni::JNIEnv& env_, const jni::Object<OfflineRegionDeleteCallback>& callback_) { + auto globalCallback = jni::NewGlobal<jni::EnvAttachingDeleter>(env_, callback_); + 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()) + callback = std::make_shared<decltype(globalCallback)>(std::move(globalCallback)) ](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); + OfflineRegionDeleteCallback::onError(*env, *callback, error); } else { - OfflineRegionDeleteCallback::onDelete(*env, jni::Object<OfflineRegionDeleteCallback>(*callback)); + OfflineRegionDeleteCallback::onDelete(*env, *callback); } }); } -void OfflineRegion::updateOfflineRegionMetadata(jni::JNIEnv& env_, jni::Array<jni::jbyte> jMetadata, jni::Object<OfflineRegionUpdateMetadataCallback> callback_) { - - // Convert +void OfflineRegion::updateOfflineRegionMetadata(jni::JNIEnv& env_, const jni::Array<jni::jbyte>& jMetadata, const jni::Object<OfflineRegionUpdateMetadataCallback>& callback_) { auto metadata = OfflineRegion::metadata(env_, jMetadata); + auto globalCallback = jni::NewGlobal<jni::EnvAttachingDeleter>(env_, callback_); 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()) + callback = std::make_shared<decltype(globalCallback)>(std::move(globalCallback)) ](mbgl::expected<mbgl::OfflineRegionMetadata, std::exception_ptr> data) mutable { // Reattach, the callback comes from a different thread android::UniqueEnv env = android::AttachEnv(); if (data) { - OfflineRegionUpdateMetadataCallback::onUpdate(*env, jni::Object<OfflineRegionUpdateMetadataCallback>(*callback), std::move(*data)); + OfflineRegionUpdateMetadataCallback::onUpdate(*env, *callback, std::move(*data)); } else { - OfflineRegionUpdateMetadataCallback::onError(*env, jni::Object<OfflineRegionUpdateMetadataCallback>(*callback), data.error()); + OfflineRegionUpdateMetadataCallback::onError(*env, *callback, data.error()); } }); } -jni::Object<OfflineRegion> OfflineRegion::New(jni::JNIEnv& env, jni::Object<FileSource> jFileSource, mbgl::OfflineRegion region) { +jni::Local<jni::Object<OfflineRegion>> OfflineRegion::New(jni::JNIEnv& env, const jni::Object<FileSource>& jFileSource, mbgl::OfflineRegion region) { // Definition auto definition = region.getDefinition().match( [&](const mbgl::OfflineTilePyramidRegionDefinition def) { - return jni::Object<OfflineRegionDefinition>( - *OfflineTilePyramidRegionDefinition::New(env, def)); + return OfflineTilePyramidRegionDefinition::New(env, def); }, [&](const mbgl::OfflineGeometryRegionDefinition def) { - return jni::Object<OfflineRegionDefinition>( - *OfflineGeometryRegionDefinition::New(env, def)); + return OfflineGeometryRegionDefinition::New(env, def); }); - // 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); + static auto& javaClass = jni::Class<OfflineRegion>::Singleton(env); + static auto constructor = javaClass.GetConstructor<jni::jlong, jni::Object<FileSource>, jni::jlong, jni::Object<OfflineRegionDefinition>, jni::Array<jni::jbyte>>(env); - return jregion; + return 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, + OfflineRegion::metadata(env, region.getMetadata())); } -jni::Array<jni::jbyte> OfflineRegion::metadata(jni::JNIEnv& env, mbgl::OfflineRegionMetadata metadata_) { +jni::Local<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); @@ -192,7 +168,7 @@ jni::Array<jni::jbyte> OfflineRegion::metadata(jni::JNIEnv& env, mbgl::OfflineRe return metadata; } -mbgl::OfflineRegionMetadata OfflineRegion::metadata(jni::JNIEnv& env, jni::Array<jni::jbyte> metadata_) { +mbgl::OfflineRegionMetadata OfflineRegion::metadata(jni::JNIEnv& env, const jni::Array<jni::jbyte>& metadata_) { std::size_t length = metadata_.Length(env); auto metadata_tmp = std::vector<jni::jbyte>(); metadata_tmp.resize(length); @@ -201,20 +177,18 @@ mbgl::OfflineRegionMetadata OfflineRegion::metadata(jni::JNIEnv& env, jni::Array 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); + jni::Class<OfflineRegionObserver>::Singleton(env); + jni::Class<OfflineRegionStatusCallback>::Singleton(env); + jni::Class<OfflineRegionDeleteCallback>::Singleton(env); + jni::Class<OfflineRegionUpdateMetadataCallback>::Singleton(env); - javaClass = *jni::Class<OfflineRegion>::Find(env).NewGlobalRef(env).release(); + static auto& javaClass = jni::Class<OfflineRegion>::Singleton(env); #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>>, + jni::MakePeer<OfflineRegion, jni::jlong, const jni::Object<FileSource>&>, "initialize", "finalize", METHOD(&OfflineRegion::setOfflineRegionObserver, "setOfflineRegionObserver"), @@ -227,94 +201,63 @@ void OfflineRegion::registerNative(jni::JNIEnv& env) { // 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, + const jni::Object<OfflineRegion::OfflineRegionStatusCallback>& callback, std::exception_ptr error) { + static auto& javaClass = jni::Class<OfflineRegion::OfflineRegionStatusCallback>::Singleton(env); static auto method = javaClass.GetMethod<void (jni::String)>(env, "onError"); - std::string message = mbgl::util::toString(error); - auto jmessage = jni::Make<jni::String>(env, message); - callback.Call(env, method, jmessage); - jni::DeleteLocalRef(env, jmessage); + + callback.Call(env, method, jni::Make<jni::String>(env, mbgl::util::toString(error))); } void OfflineRegion::OfflineRegionStatusCallback::onStatus(jni::JNIEnv& env, - jni::Object<OfflineRegion::OfflineRegionStatusCallback> callback, + const 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& javaClass = jni::Class<OfflineRegion::OfflineRegionStatusCallback>::Singleton(env); static auto method = javaClass.GetMethod<void (jni::Object<OfflineRegionStatus>)>(env, "onStatus"); - callback.Call(env, method, jStatus); - jni::DeleteLocalRef(env, jStatus); + + callback.Call(env, method, OfflineRegionStatus::New(env, std::move(*status))); } // 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, + const jni::Object<OfflineRegion::OfflineRegionDeleteCallback>& callback, std::exception_ptr error) { + static auto& javaClass = jni::Class<OfflineRegion::OfflineRegionDeleteCallback>::Singleton(env); static auto method = javaClass.GetMethod<void (jni::String)>(env, "onError"); - std::string message = mbgl::util::toString(error); - auto jmessage = jni::Make<jni::String>(env, message); - callback.Call(env, method, jmessage); - jni::DeleteLocalRef(env, jmessage); + + callback.Call(env, method, jni::Make<jni::String>(env, mbgl::util::toString(error))); } -void OfflineRegion::OfflineRegionDeleteCallback::onDelete(jni::JNIEnv& env, jni::Object<OfflineRegion::OfflineRegionDeleteCallback> callback) { +void OfflineRegion::OfflineRegionDeleteCallback::onDelete(jni::JNIEnv& env, const jni::Object<OfflineRegion::OfflineRegionDeleteCallback>& callback) { // Trigger callback + static auto& javaClass = jni::Class<OfflineRegion::OfflineRegionDeleteCallback>::Singleton(env); 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, + const jni::Object<OfflineRegion::OfflineRegionUpdateMetadataCallback>& callback, std::exception_ptr error) { + static auto& javaClass = jni::Class<OfflineRegion::OfflineRegionUpdateMetadataCallback>::Singleton(env); static auto method = javaClass.GetMethod<void (jni::String)>(env, "onError"); - std::string message = mbgl::util::toString(error); - auto jmessage = jni::Make<jni::String>(env, message); - callback.Call(env, method, jmessage); - jni::DeleteLocalRef(env, jmessage); + + callback.Call(env, method, jni::Make<jni::String>(env, mbgl::util::toString(error))); } void OfflineRegion::OfflineRegionUpdateMetadataCallback::onUpdate(jni::JNIEnv& env, - jni::Object<OfflineRegion::OfflineRegionUpdateMetadataCallback> callback, + const 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& javaClass = jni::Class<OfflineRegion::OfflineRegionUpdateMetadataCallback>::Singleton(env); static auto method = javaClass.GetMethod<void (jni::Array<jni::jbyte>)>(env, "onUpdate"); - callback.Call(env, method, jMetadata); - jni::DeleteLocalRef(env, jMetadata); + + callback.Call(env, method, OfflineRegion::metadata(env, std::move(*metadata))); } } // namespace android |