Rename Gradle targets Android (#2226)

This commit is contained in:
Bart Louwers
2024-04-02 23:15:50 +02:00
committed by GitHub
parent 37170ed61c
commit 9f8ae7a98b
1081 changed files with 132 additions and 370 deletions

View File

@@ -0,0 +1,347 @@
#include "offline_manager.hpp"
#include <mbgl/storage/file_source_manager.hpp>
#include <mbgl/storage/resource.hpp>
#include <mbgl/util/string.hpp>
#include "attach_env.hpp"
namespace mbgl {
namespace android {
namespace {
// Reattach, the callback comes from a different thread
void handleException(std::exception_ptr exception,
const jni::Object<OfflineManager::FileSourceCallback>& callback,
android::UniqueEnv env = android::AttachEnv()) {
if (exception) {
OfflineManager::FileSourceCallback::onError(
*env, callback, jni::Make<jni::String>(*env, mbgl::util::toString(exception)));
} else {
OfflineManager::FileSourceCallback::onSuccess(*env, callback);
}
}
} // namespace
// OfflineManager //
OfflineManager::OfflineManager(jni::JNIEnv& env, const jni::Object<FileSource>& jFileSource)
: fileSource(std::static_pointer_cast<mbgl::DatabaseFileSource>(std::shared_ptr<mbgl::FileSource>(
mbgl::FileSourceManager::get()->getFileSource(mbgl::FileSourceType::Database,
FileSource::getSharedResourceOptions(env, jFileSource),
FileSource::getSharedClientOptions(env, jFileSource))))) {
if (!fileSource) {
ThrowNew(env, jni::FindClass(env, "java/lang/IllegalStateException"), "Offline functionality is disabled.");
}
}
OfflineManager::~OfflineManager() {}
void OfflineManager::setOfflineMapboxTileCountLimit(jni::JNIEnv&, jni::jlong limit) {
fileSource->setOfflineMapboxTileCountLimit(limit);
}
void OfflineManager::listOfflineRegions(jni::JNIEnv& env_,
const jni::Object<FileSource>& jFileSource_,
const jni::Object<ListOfflineRegionsCallback>& callback_) {
auto globalCallback = jni::NewGlobal<jni::EnvAttachingDeleter>(env_, callback_);
auto globalFilesource = jni::NewGlobal<jni::EnvAttachingDeleter>(env_, jFileSource_);
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::make_shared<decltype(globalCallback)>(std::move(globalCallback)),
jFileSource = std::make_shared<decltype(globalFilesource)>(std::move(globalFilesource))](
mbgl::expected<mbgl::OfflineRegions, std::exception_ptr> regions) mutable {
// Reattach, the callback comes from a different thread
android::UniqueEnv env = android::AttachEnv();
if (regions) {
OfflineManager::ListOfflineRegionsCallback::onList(*env, *jFileSource, *callback, *regions);
} else {
OfflineManager::ListOfflineRegionsCallback::onError(*env, *callback, regions.error());
}
});
}
void OfflineManager::createOfflineRegion(jni::JNIEnv& env_,
const jni::Object<FileSource>& jFileSource_,
const jni::Object<OfflineRegionDefinition>& definition_,
const jni::Array<jni::jbyte>& metadata_,
const jni::Object<CreateOfflineRegionCallback>& callback_) {
// Convert
auto definition = OfflineRegionDefinition::getDefinition(env_, definition_);
mbgl::OfflineRegionMetadata metadata;
if (metadata_) {
metadata = OfflineRegion::metadata(env_, metadata_);
}
auto globalCallback = jni::NewGlobal<jni::EnvAttachingDeleter>(env_, callback_);
auto globalFilesource = jni::NewGlobal<jni::EnvAttachingDeleter>(env_, jFileSource_);
// 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::make_shared<decltype(globalCallback)>(std::move(globalCallback)),
jFileSource = std::make_shared<decltype(globalFilesource)>(std::move(globalFilesource))](
mbgl::expected<mbgl::OfflineRegion, std::exception_ptr> region) mutable {
// Reattach, the callback comes from a different thread
android::UniqueEnv env = android::AttachEnv();
if (region) {
OfflineManager::CreateOfflineRegionCallback::onCreate(*env, *jFileSource, *callback, *region);
} else {
OfflineManager::CreateOfflineRegionCallback::onError(*env, *callback, region.error());
}
});
}
void OfflineManager::mergeOfflineRegions(jni::JNIEnv& env_,
const jni::Object<FileSource>& jFileSource_,
const jni::String& jString_,
const jni::Object<MergeOfflineRegionsCallback>& callback_) {
auto globalCallback = jni::NewGlobal<jni::EnvAttachingDeleter>(env_, callback_);
auto globalFilesource = jni::NewGlobal<jni::EnvAttachingDeleter>(env_, jFileSource_);
auto path = jni::Make<std::string>(env_, jString_);
fileSource->mergeOfflineRegions(
path,
[
// 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::make_shared<decltype(globalCallback)>(std::move(globalCallback)),
jFileSource = std::make_shared<decltype(globalFilesource)>(std::move(globalFilesource))](
mbgl::expected<mbgl::OfflineRegions, std::exception_ptr> regions) mutable {
// Reattach, the callback comes from a different thread
android::UniqueEnv env = android::AttachEnv();
if (regions) {
OfflineManager::MergeOfflineRegionsCallback::onMerge(*env, *jFileSource, *callback, *regions);
} else {
OfflineManager::MergeOfflineRegionsCallback::onError(*env, *callback, regions.error());
}
});
}
void OfflineManager::resetDatabase(jni::JNIEnv& env_, const jni::Object<FileSourceCallback>& callback_) {
auto globalCallback = jni::NewGlobal<jni::EnvAttachingDeleter>(env_, callback_);
fileSource->resetDatabase([
// Keep a shared ptr to a global reference of the
// callback so they are not GC'd in the meanwhile
callback = std::make_shared<decltype(globalCallback)>(std::move(globalCallback))](
std::exception_ptr exception) mutable { handleException(exception, *callback); });
}
void OfflineManager::packDatabase(jni::JNIEnv& env_, const jni::Object<FileSourceCallback>& callback_) {
auto globalCallback = jni::NewGlobal<jni::EnvAttachingDeleter>(env_, callback_);
fileSource->packDatabase([
// Keep a shared ptr to a global reference of the
// callback so they are not GC'd in the meanwhile
callback = std::make_shared<decltype(globalCallback)>(std::move(globalCallback))](
std::exception_ptr exception) mutable { handleException(exception, *callback); });
}
void OfflineManager::invalidateAmbientCache(jni::JNIEnv& env_, const jni::Object<FileSourceCallback>& callback_) {
auto globalCallback = jni::NewGlobal<jni::EnvAttachingDeleter>(env_, callback_);
fileSource->invalidateAmbientCache(
[
// Keep a shared ptr to a global reference of the callback so
// they are not GC'd in the meanwhile
callback = std::make_shared<decltype(globalCallback)>(std::move(globalCallback))](
std::exception_ptr exception) mutable { handleException(exception, *callback); });
}
void OfflineManager::clearAmbientCache(jni::JNIEnv& env_, const jni::Object<FileSourceCallback>& callback_) {
auto globalCallback = jni::NewGlobal<jni::EnvAttachingDeleter>(env_, callback_);
fileSource->clearAmbientCache([
// Keep a shared ptr to a global reference of the callback so
// they are not GC'd in the meanwhile
callback = std::make_shared<decltype(globalCallback)>(std::move(globalCallback))](
std::exception_ptr exception) mutable { handleException(exception, *callback); });
}
void OfflineManager::setMaximumAmbientCacheSize(jni::JNIEnv& env_,
const jni::jlong size_,
const jni::Object<FileSourceCallback>& callback_) {
auto globalCallback = jni::NewGlobal<jni::EnvAttachingDeleter>(env_, callback_);
fileSource->setMaximumAmbientCacheSize(
size_,
[
// Keep a shared ptr to a global reference of the callback so
// they are not GC'd in the meanwhile
callback = std::make_shared<decltype(globalCallback)>(std::move(globalCallback))](
std::exception_ptr exception) mutable { handleException(exception, *callback); });
}
void OfflineManager::runPackDatabaseAutomatically(jni::JNIEnv&, jboolean autopack) {
fileSource->runPackDatabaseAutomatically(autopack);
}
// FileSource::FileSourceCallback //
void OfflineManager::FileSourceCallback::onSuccess(jni::JNIEnv& env,
const jni::Object<OfflineManager::FileSourceCallback>& callback) {
static auto& javaClass = jni::Class<OfflineManager::FileSourceCallback>::Singleton(env);
static auto method = javaClass.GetMethod<void()>(env, "onSuccess");
callback.Call(env, method);
}
void OfflineManager::FileSourceCallback::onError(jni::JNIEnv& env,
const jni::Object<OfflineManager::FileSourceCallback>& callback,
const jni::String& message) {
static auto& javaClass = jni::Class<OfflineManager::FileSourceCallback>::Singleton(env);
static auto method = javaClass.GetMethod<void(jni::String)>(env, "onError");
callback.Call(env, method, message);
}
void OfflineManager::registerNative(jni::JNIEnv& env) {
jni::Class<ListOfflineRegionsCallback>::Singleton(env);
jni::Class<CreateOfflineRegionCallback>::Singleton(env);
jni::Class<MergeOfflineRegionsCallback>::Singleton(env);
jni::Class<FileSourceCallback>::Singleton(env);
static auto& javaClass = jni::Class<OfflineManager>::Singleton(env);
#define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name)
jni::RegisterNativePeer<OfflineManager>(
env,
javaClass,
"nativePtr",
jni::MakePeer<OfflineManager, const jni::Object<FileSource>&>,
"initialize",
"finalize",
METHOD(&OfflineManager::setOfflineMapboxTileCountLimit, "setOfflineMapboxTileCountLimit"),
METHOD(&OfflineManager::listOfflineRegions, "listOfflineRegions"),
METHOD(&OfflineManager::createOfflineRegion, "createOfflineRegion"),
METHOD(&OfflineManager::mergeOfflineRegions, "mergeOfflineRegions"),
METHOD(&OfflineManager::resetDatabase, "nativeResetDatabase"),
METHOD(&OfflineManager::packDatabase, "nativePackDatabase"),
METHOD(&OfflineManager::invalidateAmbientCache, "nativeInvalidateAmbientCache"),
METHOD(&OfflineManager::clearAmbientCache, "nativeClearAmbientCache"),
METHOD(&OfflineManager::setMaximumAmbientCacheSize, "nativeSetMaximumAmbientCacheSize"),
METHOD(&OfflineManager::runPackDatabaseAutomatically, "runPackDatabaseAutomatically"),
METHOD(&OfflineManager::putResourceWithUrl, "putResourceWithUrl"));
}
// OfflineManager::ListOfflineRegionsCallback //
void OfflineManager::ListOfflineRegionsCallback::onError(
jni::JNIEnv& env,
const jni::Object<OfflineManager::ListOfflineRegionsCallback>& callback,
std::exception_ptr error) {
static auto& javaClass = jni::Class<OfflineManager::ListOfflineRegionsCallback>::Singleton(env);
static auto method = javaClass.GetMethod<void(jni::String)>(env, "onError");
callback.Call(env, method, jni::Make<jni::String>(env, mbgl::util::toString(error)));
}
void OfflineManager::ListOfflineRegionsCallback::onList(
jni::JNIEnv& env,
const jni::Object<FileSource>& jFileSource,
const jni::Object<OfflineManager::ListOfflineRegionsCallback>& callback,
mbgl::OfflineRegions& regions) {
static auto& javaClass = jni::Class<OfflineManager::ListOfflineRegionsCallback>::Singleton(env);
static auto method = javaClass.GetMethod<void(jni::Array<jni::Object<OfflineRegion>>)>(env, "onList");
std::size_t index = 0;
auto jregions = jni::Array<jni::Object<OfflineRegion>>::New(env, regions.size());
for (auto& region : regions) {
jregions.Set(env, index, OfflineRegion::New(env, jFileSource, std::move(region)));
index++;
}
callback.Call(env, method, jregions);
}
// OfflineManager::CreateOfflineRegionCallback //
void OfflineManager::CreateOfflineRegionCallback::onError(
jni::JNIEnv& env,
const jni::Object<OfflineManager::CreateOfflineRegionCallback>& callback,
std::exception_ptr error) {
static auto& javaClass = jni::Class<OfflineManager::CreateOfflineRegionCallback>::Singleton(env);
static auto method = javaClass.GetMethod<void(jni::String)>(env, "onError");
callback.Call(env, method, jni::Make<jni::String>(env, mbgl::util::toString(error)));
}
void OfflineManager::CreateOfflineRegionCallback::onCreate(
jni::JNIEnv& env,
const jni::Object<FileSource>& jFileSource,
const jni::Object<OfflineManager::CreateOfflineRegionCallback>& callback,
mbgl::OfflineRegion& region) {
static auto& javaClass = jni::Class<OfflineManager::CreateOfflineRegionCallback>::Singleton(env);
static auto method = javaClass.GetMethod<void(jni::Object<OfflineRegion>)>(env, "onCreate");
callback.Call(env, method, OfflineRegion::New(env, jFileSource, std::move(region)));
}
// OfflineManager::MergeOfflineRegionsCallback //
void OfflineManager::MergeOfflineRegionsCallback::onError(
jni::JNIEnv& env,
const jni::Object<OfflineManager::MergeOfflineRegionsCallback>& callback,
std::exception_ptr error) {
static auto& javaClass = jni::Class<OfflineManager::MergeOfflineRegionsCallback>::Singleton(env);
static auto method = javaClass.GetMethod<void(jni::String)>(env, "onError");
callback.Call(env, method, jni::Make<jni::String>(env, mbgl::util::toString(error)));
}
void OfflineManager::MergeOfflineRegionsCallback::onMerge(jni::JNIEnv& env,
const jni::Object<FileSource>& jFileSource,
const jni::Object<MergeOfflineRegionsCallback>& callback,
mbgl::OfflineRegions& regions) {
static auto& javaClass = jni::Class<OfflineManager::MergeOfflineRegionsCallback>::Singleton(env);
static auto method = javaClass.GetMethod<void(jni::Array<jni::Object<OfflineRegion>>)>(env, "onMerge");
std::size_t index = 0;
auto jregions = jni::Array<jni::Object<OfflineRegion>>::New(env, regions.size());
for (auto& region : regions) {
jregions.Set(env, index, OfflineRegion::New(env, jFileSource, std::move(region)));
index++;
}
callback.Call(env, method, jregions);
}
void OfflineManager::putResourceWithUrl(jni::JNIEnv& env,
const jni::String& url_,
const jni::Array<jni::jbyte>& arr,
jlong modified,
jlong expires,
const jni::String& eTag_,
jboolean mustRevalidate) {
auto url = jni::Make<std::string>(env, url_);
auto data = std::make_shared<std::string>(arr.Length(env), char());
jni::GetArrayRegion(env, *arr, 0, data->size(), reinterpret_cast<jbyte*>(&(*data)[0]));
mbgl::Resource resource(mbgl::Resource::Kind::Unknown, url);
mbgl::Response response;
response.data = data;
response.mustRevalidate = mustRevalidate;
if (eTag_) {
response.etag = jni::Make<std::string>(env, eTag_);
}
if (modified > 0) {
response.modified = Timestamp(mbgl::Seconds(modified));
}
if (expires > 0) {
response.expires = Timestamp(mbgl::Seconds(expires));
}
fileSource->put(resource, response);
}
} // namespace android
} // namespace mbgl

View File

@@ -0,0 +1,132 @@
#pragma once
#include <mbgl/storage/offline.hpp>
#include <jni/jni.hpp>
#include "../file_source.hpp"
#include "offline_region.hpp"
#include "offline_region_definition.hpp"
#include "../java_types.hpp"
#include <memory>
namespace mbgl {
namespace android {
class OfflineManager {
public:
class ListOfflineRegionsCallback {
public:
static constexpr auto Name() {
return "org/maplibre/android/offline/"
"OfflineManager$ListOfflineRegionsCallback";
}
static void onError(jni::JNIEnv&,
const jni::Object<OfflineManager::ListOfflineRegionsCallback>&,
std::exception_ptr);
static void onList(jni::JNIEnv&,
const jni::Object<FileSource>&,
const jni::Object<OfflineManager::ListOfflineRegionsCallback>&,
mbgl::OfflineRegions&);
};
class CreateOfflineRegionCallback {
public:
static constexpr auto Name() {
return "org/maplibre/android/offline/"
"OfflineManager$CreateOfflineRegionCallback";
}
static void onError(jni::JNIEnv&,
const jni::Object<OfflineManager::CreateOfflineRegionCallback>&,
std::exception_ptr);
static void onCreate(jni::JNIEnv&,
const jni::Object<FileSource>&,
const jni::Object<OfflineManager::CreateOfflineRegionCallback>&,
mbgl::OfflineRegion&);
};
class MergeOfflineRegionsCallback {
public:
static constexpr auto Name() {
return "org/maplibre/android/offline/"
"OfflineManager$MergeOfflineRegionsCallback";
}
static void onError(jni::JNIEnv&,
const jni::Object<OfflineManager::MergeOfflineRegionsCallback>&,
std::exception_ptr);
static void onMerge(jni::JNIEnv&,
const jni::Object<FileSource>&,
const jni::Object<MergeOfflineRegionsCallback>&,
mbgl::OfflineRegions&);
};
struct FileSourceCallback {
static constexpr auto Name() {
return "org/maplibre/android/offline/"
"OfflineManager$FileSourceCallback";
}
static void onSuccess(jni::JNIEnv&, const jni::Object<OfflineManager::FileSourceCallback>&);
static void onError(jni::JNIEnv&, const jni::Object<OfflineManager::FileSourceCallback>&, const jni::String&);
};
static constexpr auto Name() { return "org/maplibre/android/offline/OfflineManager"; };
static void registerNative(jni::JNIEnv&);
OfflineManager(jni::JNIEnv&, const jni::Object<FileSource>&);
~OfflineManager();
void setOfflineMapboxTileCountLimit(jni::JNIEnv&, jni::jlong limit);
void listOfflineRegions(jni::JNIEnv&,
const jni::Object<FileSource>&,
const jni::Object<ListOfflineRegionsCallback>& callback);
void createOfflineRegion(jni::JNIEnv&,
const jni::Object<FileSource>& jFileSource_,
const jni::Object<OfflineRegionDefinition>& definition,
const jni::Array<jni::jbyte>& metadata,
const jni::Object<OfflineManager::CreateOfflineRegionCallback>& callback);
void mergeOfflineRegions(jni::JNIEnv&,
const jni::Object<FileSource>&,
const jni::String&,
const jni::Object<MergeOfflineRegionsCallback>&);
void putResourceWithUrl(jni::JNIEnv&,
const jni::String& url,
const jni::Array<jni::jbyte>& data,
jlong modified,
jlong expires,
const jni::String& eTag,
jboolean mustRevalidate);
void resetDatabase(jni::JNIEnv&, const jni::Object<FileSourceCallback>& callback_);
void packDatabase(jni::JNIEnv&, const jni::Object<FileSourceCallback>& callback_);
void invalidateAmbientCache(jni::JNIEnv&, const jni::Object<FileSourceCallback>& callback_);
void clearAmbientCache(jni::JNIEnv&, const jni::Object<FileSourceCallback>& callback_);
void setMaximumAmbientCacheSize(jni::JNIEnv&,
const jni::jlong size,
const jni::Object<FileSourceCallback>& callback_);
void runPackDatabaseAutomatically(jni::JNIEnv&, jboolean autopack);
private:
std::shared_ptr<mbgl::DatabaseFileSource> fileSource;
};
} // namespace android
} // namespace mbgl

View File

@@ -0,0 +1,338 @@
#include "offline_region.hpp"
#include <mbgl/storage/file_source_manager.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"
namespace mbgl {
namespace android {
// OfflineRegion //
OfflineRegion::OfflineRegion(jni::JNIEnv& env, jni::jlong offlineRegionPtr, const jni::Object<FileSource>& jFileSource)
: region(reinterpret_cast<mbgl::OfflineRegion*>(offlineRegionPtr)),
fileSource(std::static_pointer_cast<mbgl::DatabaseFileSource>(std::shared_ptr<mbgl::FileSource>(
mbgl::FileSourceManager::get()->getFileSource(mbgl::FileSourceType::Database,
FileSource::getSharedResourceOptions(env, jFileSource),
FileSource::getSharedClientOptions(env, jFileSource))))) {
if (!fileSource) {
ThrowNew(env, jni::FindClass(env, "java/lang/IllegalStateException"), "Offline functionality is disabled.");
}
}
OfflineRegion::~OfflineRegion() {}
void OfflineRegion::setOfflineRegionObserver(jni::JNIEnv& env_,
const jni::Object<OfflineRegion::OfflineRegionObserver>& callback) {
// Define the observer
class Observer : public mbgl::OfflineRegionObserver {
public:
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();
static auto& javaClass = jni::Class<OfflineRegion::OfflineRegionObserver>::Singleton(*env);
static auto method = javaClass.GetMethod<void(jni::Object<OfflineRegionStatus>)>(*env, "onStatusChanged");
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();
static auto& javaClass = jni::Class<OfflineRegion::OfflineRegionObserver>::Singleton(*env);
static auto method = javaClass.GetMethod<void(jni::Object<mbgl::android::OfflineRegionError>)>(*env,
"onError");
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();
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::Global<jni::Object<OfflineRegion::OfflineRegionObserver>, jni::EnvAttachingDeleter> callback;
};
// Set the observer
fileSource->setOfflineRegionObserver(
*region, std::make_unique<Observer>(jni::NewGlobal<jni::EnvAttachingDeleter>(env_, callback)));
}
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_,
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::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, *callback, std::move(*status));
} else {
OfflineRegionStatusCallback::onError(*env, *callback, status.error());
}
});
}
void OfflineRegion::deleteOfflineRegion(jni::JNIEnv& env_, const jni::Object<OfflineRegionDeleteCallback>& callback_) {
auto globalCallback = jni::NewGlobal<jni::EnvAttachingDeleter>(env_, callback_);
fileSource->deleteOfflineRegion(*region,
[
// Ensure the object is not gc'd in the meanwhile
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, *callback, error);
} else {
OfflineRegionDeleteCallback::onDelete(*env, *callback);
}
});
}
void OfflineRegion::invalidateOfflineRegion(jni::JNIEnv& env_,
const jni::Object<OfflineRegionInvalidateCallback>& callback_) {
auto globalCallback = jni::NewGlobal<jni::EnvAttachingDeleter>(env_, callback_);
fileSource->invalidateOfflineRegion(*region,
[
// Ensure the object is not gc'd in the meanwhile
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) {
OfflineRegionInvalidateCallback::onError(*env, *callback, error);
} else {
OfflineRegionInvalidateCallback::onInvalidate(*env, *callback);
}
});
}
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::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, *callback, std::move(*data));
} else {
OfflineRegionUpdateMetadataCallback::onError(*env, *callback, data.error());
}
});
}
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 OfflineTilePyramidRegionDefinition::New(env, def);
},
[&](const mbgl::OfflineGeometryRegionDefinition def) {
return OfflineGeometryRegionDefinition::New(env, def);
});
// Create region java object
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 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::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);
metadata.SetRegion<std::vector<jni::jbyte>>(env, 0, convertedMetadata);
return 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);
metadata_.GetRegion<std::vector<jni::jbyte>>(env, 0, metadata_tmp);
auto metadata = std::vector<uint8_t>(metadata_tmp.begin(), metadata_tmp.end());
return metadata;
}
void OfflineRegion::registerNative(jni::JNIEnv& env) {
jni::Class<OfflineRegionObserver>::Singleton(env);
jni::Class<OfflineRegionStatusCallback>::Singleton(env);
jni::Class<OfflineRegionDeleteCallback>::Singleton(env);
jni::Class<OfflineRegionUpdateMetadataCallback>::Singleton(env);
jni::Class<OfflineRegionInvalidateCallback>::Singleton(env);
static auto& javaClass = jni::Class<OfflineRegion>::Singleton(env);
#define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name)
jni::RegisterNativePeer<OfflineRegion>(
env,
javaClass,
"nativePtr",
jni::MakePeer<OfflineRegion, jni::jlong, const jni::Object<FileSource>&>,
"initialize",
"finalize",
METHOD(&OfflineRegion::setOfflineRegionObserver, "setOfflineRegionObserver"),
METHOD(&OfflineRegion::setOfflineRegionDownloadState, "setOfflineRegionDownloadState"),
METHOD(&OfflineRegion::getOfflineRegionStatus, "getOfflineRegionStatus"),
METHOD(&OfflineRegion::deleteOfflineRegion, "deleteOfflineRegion"),
METHOD(&OfflineRegion::invalidateOfflineRegion, "invalidateOfflineRegion"),
METHOD(&OfflineRegion::updateOfflineRegionMetadata, "updateOfflineRegionMetadata"));
}
// OfflineRegionObserver //
// OfflineRegionStatusCallback //
void OfflineRegion::OfflineRegionStatusCallback::onError(
jni::JNIEnv& env,
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");
callback.Call(env, method, jni::Make<jni::String>(env, mbgl::util::toString(error)));
}
void OfflineRegion::OfflineRegionStatusCallback::onStatus(
jni::JNIEnv& env,
const jni::Object<OfflineRegion::OfflineRegionStatusCallback>& callback,
std::optional<mbgl::OfflineRegionStatus> status) {
static auto& javaClass = jni::Class<OfflineRegion::OfflineRegionStatusCallback>::Singleton(env);
static auto method = javaClass.GetMethod<void(jni::Object<OfflineRegionStatus>)>(env, "onStatus");
callback.Call(env, method, OfflineRegionStatus::New(env, std::move(*status)));
}
// OfflineRegionDeleteCallback //
void OfflineRegion::OfflineRegionDeleteCallback::onError(
jni::JNIEnv& env,
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");
callback.Call(env, method, jni::Make<jni::String>(env, mbgl::util::toString(error)));
}
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 //
void OfflineRegion::OfflineRegionUpdateMetadataCallback::onError(
jni::JNIEnv& env,
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");
callback.Call(env, method, jni::Make<jni::String>(env, mbgl::util::toString(error)));
}
void OfflineRegion::OfflineRegionUpdateMetadataCallback::onUpdate(
jni::JNIEnv& env,
const jni::Object<OfflineRegion::OfflineRegionUpdateMetadataCallback>& callback,
std::optional<mbgl::OfflineRegionMetadata> metadata) {
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, OfflineRegion::metadata(env, std::move(*metadata)));
}
// OfflineRegionInvalidateCallback //
void OfflineRegion::OfflineRegionInvalidateCallback::onError(
jni::JNIEnv& env,
const jni::Object<OfflineRegion::OfflineRegionInvalidateCallback>& callback,
std::exception_ptr error) {
static auto& javaClass = jni::Class<OfflineRegion::OfflineRegionInvalidateCallback>::Singleton(env);
static auto method = javaClass.GetMethod<void(jni::String)>(env, "onError");
callback.Call(env, method, jni::Make<jni::String>(env, mbgl::util::toString(error)));
}
void OfflineRegion::OfflineRegionInvalidateCallback::onInvalidate(
jni::JNIEnv& env, const jni::Object<OfflineRegion::OfflineRegionInvalidateCallback>& callback) {
static auto& javaClass = jni::Class<OfflineRegion::OfflineRegionInvalidateCallback>::Singleton(env);
static auto method = javaClass.GetMethod<void()>(env, "onInvalidate");
callback.Call(env, method);
}
} // namespace android
} // namespace mbgl

View File

@@ -0,0 +1,111 @@
#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 "org/maplibre/android/offline/"
"OfflineRegion$OfflineRegionObserver";
};
};
class OfflineRegionStatusCallback {
public:
static constexpr auto Name() {
return "org/maplibre/android/offline/"
"OfflineRegion$OfflineRegionStatusCallback";
};
static void onError(jni::JNIEnv&, const jni::Object<OfflineRegionStatusCallback>&, std::exception_ptr);
static void onStatus(jni::JNIEnv&,
const jni::Object<OfflineRegionStatusCallback>&,
std::optional<mbgl::OfflineRegionStatus>);
};
class OfflineRegionDeleteCallback {
public:
static constexpr auto Name() {
return "org/maplibre/android/offline/"
"OfflineRegion$OfflineRegionDeleteCallback";
};
static void onError(jni::JNIEnv&, const jni::Object<OfflineRegionDeleteCallback>&, std::exception_ptr);
static void onDelete(jni::JNIEnv&, const jni::Object<OfflineRegionDeleteCallback>&);
};
class OfflineRegionInvalidateCallback {
public:
static constexpr auto Name() {
return "org/maplibre/android/offline/"
"OfflineRegion$OfflineRegionInvalidateCallback";
};
static void onError(jni::JNIEnv&, const jni::Object<OfflineRegionInvalidateCallback>&, std::exception_ptr);
static void onInvalidate(jni::JNIEnv&, const jni::Object<OfflineRegionInvalidateCallback>&);
};
class OfflineRegionUpdateMetadataCallback {
public:
static constexpr auto Name() {
return "org/maplibre/android/offline/"
"OfflineRegion$OfflineRegionUpdateMetadataCallback";
};
static void onError(jni::JNIEnv&, const jni::Object<OfflineRegionUpdateMetadataCallback>&, std::exception_ptr);
static void onUpdate(jni::JNIEnv&,
const jni::Object<OfflineRegionUpdateMetadataCallback>&,
std::optional<mbgl::OfflineRegionMetadata>);
};
static constexpr auto Name() { return "org/maplibre/android/offline/OfflineRegion"; };
OfflineRegion(jni::JNIEnv&, jni::jlong, const jni::Object<FileSource>&);
~OfflineRegion();
void setOfflineRegionObserver(jni::JNIEnv&, const jni::Object<OfflineRegion::OfflineRegionObserver>&);
void setOfflineRegionDownloadState(jni::JNIEnv&, jni::jint);
void getOfflineRegionStatus(jni::JNIEnv&, const jni::Object<OfflineRegion::OfflineRegionStatusCallback>&);
void deleteOfflineRegion(jni::JNIEnv&, const jni::Object<OfflineRegionDeleteCallback>&);
void invalidateOfflineRegion(jni::JNIEnv&, const jni::Object<OfflineRegionInvalidateCallback>&);
void updateOfflineRegionMetadata(jni::JNIEnv&,
const jni::Array<jni::jbyte>&,
const jni::Object<OfflineRegionUpdateMetadataCallback>&);
static jni::Local<jni::Object<OfflineRegion>> New(jni::JNIEnv&,
const jni::Object<FileSource>&,
mbgl::OfflineRegion);
static jni::Local<jni::Array<jni::jbyte>> metadata(jni::JNIEnv&, mbgl::OfflineRegionMetadata);
static mbgl::OfflineRegionMetadata metadata(jni::JNIEnv&, const jni::Array<jni::jbyte>&);
static void registerNative(jni::JNIEnv&);
private:
std::unique_ptr<mbgl::OfflineRegion> region;
std::shared_ptr<mbgl::DatabaseFileSource> fileSource;
};
} // namespace android
} // namespace mbgl

View File

@@ -0,0 +1,121 @@
#include "offline_region_definition.hpp"
#include "../geometry/lat_lng_bounds.hpp"
#include "../geojson/geometry.hpp"
#include <exception>
namespace mbgl {
namespace android {
// OfflineRegionDefinition //
void OfflineRegionDefinition::registerNative(jni::JNIEnv& env) {
jni::Class<OfflineRegionDefinition>::Singleton(env);
}
mbgl::OfflineRegionDefinition OfflineRegionDefinition::getDefinition(
JNIEnv& env, const jni::Object<OfflineRegionDefinition>& jDefinition) {
if (jDefinition.IsInstanceOf(env, jni::Class<OfflineTilePyramidRegionDefinition>::Singleton(env))) {
return OfflineTilePyramidRegionDefinition::getDefinition(
env, jni::Cast(env, jni::Class<OfflineTilePyramidRegionDefinition>::Singleton(env), jDefinition));
} else if (jDefinition.IsInstanceOf(env, jni::Class<OfflineGeometryRegionDefinition>::Singleton(env))) {
return OfflineGeometryRegionDefinition::getDefinition(
env, jni::Cast(env, jni::Class<OfflineGeometryRegionDefinition>::Singleton(env), jDefinition));
}
throw std::runtime_error("Unknown offline region definition java class");
}
// OfflineTilePyramidRegionDefinition //
jni::Local<jni::Object<OfflineRegionDefinition>> OfflineTilePyramidRegionDefinition::New(
jni::JNIEnv& env, const mbgl::OfflineTilePyramidRegionDefinition& definition) {
static auto& javaClass = jni::Class<OfflineTilePyramidRegionDefinition>::Singleton(env);
static auto constructor = javaClass.GetConstructor<jni::String,
jni::Object<LatLngBounds>,
jni::jdouble,
jni::jdouble,
jni::jfloat,
jni::jboolean>(env);
return javaClass.New(env,
constructor,
jni::Make<jni::String>(env, definition.styleURL),
LatLngBounds::New(env, definition.bounds),
definition.minZoom,
definition.maxZoom,
definition.pixelRatio,
jni::jboolean(definition.includeIdeographs));
}
mbgl::OfflineTilePyramidRegionDefinition OfflineTilePyramidRegionDefinition::getDefinition(
jni::JNIEnv& env, const jni::Object<OfflineTilePyramidRegionDefinition>& jDefinition) {
// Field references
static auto& javaClass = jni::Class<OfflineTilePyramidRegionDefinition>::Singleton(env);
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");
static auto includeIdeographsF = javaClass.GetField<jni::jboolean>(env, "includeIdeographs");
return mbgl::OfflineTilePyramidRegionDefinition(jni::Make<std::string>(env, jDefinition.Get(env, styleURLF)),
LatLngBounds::getLatLngBounds(env, jDefinition.Get(env, boundsF)),
jDefinition.Get(env, minZoomF),
jDefinition.Get(env, maxZoomF),
jDefinition.Get(env, pixelRatioF),
jDefinition.Get(env, includeIdeographsF));
}
void OfflineTilePyramidRegionDefinition::registerNative(jni::JNIEnv& env) {
jni::Class<OfflineTilePyramidRegionDefinition>::Singleton(env);
}
// OfflineGeometryRegionDefinition //
jni::Local<jni::Object<OfflineRegionDefinition>> OfflineGeometryRegionDefinition::New(
jni::JNIEnv& env, const mbgl::OfflineGeometryRegionDefinition& definition) {
static auto& javaClass = jni::Class<OfflineGeometryRegionDefinition>::Singleton(env);
static auto constructor = javaClass.GetConstructor<jni::String,
jni::Object<geojson::Geometry>,
jni::jdouble,
jni::jdouble,
jni::jfloat,
jni::jboolean>(env);
return javaClass.New(env,
constructor,
jni::Make<jni::String>(env, definition.styleURL),
geojson::Geometry::New(env, definition.geometry),
definition.minZoom,
definition.maxZoom,
definition.pixelRatio,
jni::jboolean(definition.includeIdeographs));
}
mbgl::OfflineGeometryRegionDefinition OfflineGeometryRegionDefinition::getDefinition(
jni::JNIEnv& env, const jni::Object<OfflineGeometryRegionDefinition>& jDefinition) {
// Field references
static auto& javaClass = jni::Class<OfflineGeometryRegionDefinition>::Singleton(env);
static auto styleURLF = javaClass.GetField<jni::String>(env, "styleURL");
static auto geometryF = javaClass.GetField<jni::Object<geojson::Geometry>>(env, "geometry");
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");
static auto includeIdeographsF = javaClass.GetField<jni::jboolean>(env, "includeIdeographs");
return mbgl::OfflineGeometryRegionDefinition(jni::Make<std::string>(env, jDefinition.Get(env, styleURLF)),
geojson::Geometry::convert(env, jDefinition.Get(env, geometryF)),
jDefinition.Get(env, minZoomF),
jDefinition.Get(env, maxZoomF),
jDefinition.Get(env, pixelRatioF),
jDefinition.Get(env, includeIdeographsF));
}
void OfflineGeometryRegionDefinition::registerNative(jni::JNIEnv& env) {
jni::Class<OfflineGeometryRegionDefinition>::Singleton(env);
}
} // namespace android
} // namespace mbgl

View File

@@ -0,0 +1,51 @@
#pragma once
#include <mbgl/storage/offline.hpp>
#include <jni/jni.hpp>
namespace mbgl {
namespace android {
class OfflineRegionDefinition {
public:
static constexpr auto Name() { return "org/maplibre/android/offline/OfflineRegionDefinition"; };
static void registerNative(jni::JNIEnv&);
static mbgl::OfflineRegionDefinition getDefinition(JNIEnv& env,
const jni::Object<OfflineRegionDefinition>& jDefinition);
};
class OfflineTilePyramidRegionDefinition {
public:
using SuperTag = OfflineRegionDefinition;
static constexpr auto Name() {
return "org/maplibre/android/offline/"
"OfflineTilePyramidRegionDefinition";
};
static jni::Local<jni::Object<OfflineRegionDefinition>> New(jni::JNIEnv&,
const mbgl::OfflineTilePyramidRegionDefinition&);
static mbgl::OfflineTilePyramidRegionDefinition getDefinition(
jni::JNIEnv&, const jni::Object<OfflineTilePyramidRegionDefinition>&);
static void registerNative(jni::JNIEnv&);
};
class OfflineGeometryRegionDefinition {
public:
using SuperTag = OfflineRegionDefinition;
static constexpr auto Name() { return "org/maplibre/android/offline/OfflineGeometryRegionDefinition"; };
static jni::Local<jni::Object<OfflineRegionDefinition>> New(jni::JNIEnv&,
const mbgl::OfflineGeometryRegionDefinition&);
static mbgl::OfflineGeometryRegionDefinition getDefinition(jni::JNIEnv&,
const jni::Object<OfflineGeometryRegionDefinition>&);
static void registerNative(jni::JNIEnv&);
};
} // namespace android
} // namespace mbgl

View File

@@ -0,0 +1,42 @@
#include "offline_region_error.hpp"
namespace mbgl {
namespace android {
jni::Local<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;
}
static auto& javaClass = jni::Class<OfflineRegionError>::Singleton(env);
static auto constructor = javaClass.GetConstructor<jni::String, jni::String>(env);
return javaClass.New(
env, constructor, jni::Make<jni::String>(env, reason), jni::Make<jni::String>(env, error.message));
}
void OfflineRegionError::registerNative(jni::JNIEnv& env) {
jni::Class<OfflineRegionError>::Singleton(env);
}
} // namespace android
} // namespace mbgl

View File

@@ -0,0 +1,19 @@
#pragma once
#include <mbgl/storage/offline.hpp>
#include <jni/jni.hpp>
namespace mbgl {
namespace android {
class OfflineRegionError {
public:
static constexpr auto Name() { return "org/maplibre/android/offline/OfflineRegionError"; };
static jni::Local<jni::Object<OfflineRegionError>> New(jni::JNIEnv&, mbgl::Response::Error);
static void registerNative(jni::JNIEnv&);
};
} // namespace android
} // namespace mbgl

View File

@@ -0,0 +1,38 @@
#include "offline_region_status.hpp"
namespace mbgl {
namespace android {
jni::Local<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& javaClass = jni::Class<OfflineRegionStatus>::Singleton(env);
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));
}
void OfflineRegionStatus::registerNative(jni::JNIEnv& env) {
jni::Class<OfflineRegionStatus>::Singleton(env);
}
} // namespace android
} // namespace mbgl

View File

@@ -0,0 +1,19 @@
#pragma once
#include <mbgl/storage/offline.hpp>
#include <jni/jni.hpp>
namespace mbgl {
namespace android {
class OfflineRegionStatus {
public:
static constexpr auto Name() { return "org/maplibre/android/offline/OfflineRegionStatus"; };
static jni::Local<jni::Object<OfflineRegionStatus>> New(jni::JNIEnv&, mbgl::OfflineRegionStatus status);
static void registerNative(jni::JNIEnv&);
};
} // namespace android
} // namespace mbgl