#include "file_source.hpp" #include "attach_env.hpp" #include #include #include #include #include #include "asset_manager_file_source.hpp" namespace mbgl { namespace android { // FileSource // FileSource::FileSource(jni::JNIEnv& _env, const jni::String& accessToken, const jni::String& _cachePath, const jni::Object& assetManager) { std::string path = jni::Make(_env, _cachePath); mapbox::sqlite::setTempPath(path); // Create a core default file source fileSource = std::make_unique( path + DATABASE_FILE, std::make_unique(_env, assetManager)); // Set access token if (accessToken) { fileSource->setAccessToken(jni::Make(_env, accessToken)); } } FileSource::~FileSource() { } jni::Local FileSource::getAccessToken(jni::JNIEnv& env) { return jni::Make(env, fileSource->getAccessToken()); } void FileSource::setAccessToken(jni::JNIEnv& env, const jni::String& token) { fileSource->setAccessToken(jni::Make(env, token)); } void FileSource::setAPIBaseUrl(jni::JNIEnv& env, const jni::String& url) { fileSource->setAPIBaseURL(jni::Make(env, url)); } void FileSource::setResourceTransform(jni::JNIEnv& env, const jni::Object& transformCallback) { if (transformCallback) { auto global = jni::NewGlobal(env, transformCallback); resourceTransform = std::make_unique>(*Scheduler::GetCurrent(), // Capture the ResourceTransformCallback object as a managed global into // the lambda. It is released automatically when we're setting a new ResourceTransform in // a subsequent call. // Note: we're converting it to shared_ptr because this lambda is converted to a std::function, // which requires copyability of its captured variables. [callback = std::make_shared(std::move(global))] (mbgl::Resource::Kind kind, const std::string&& url_) { android::UniqueEnv _env = android::AttachEnv(); return FileSource::ResourceTransformCallback::onURL(*_env, *callback, int(kind), url_); }); fileSource->setResourceTransform(resourceTransform->self()); } else { // Reset the callback resourceTransform.reset(); fileSource->setResourceTransform({}); } } void FileSource::setResourceCachePath(jni::JNIEnv& env, const jni::String& path) { std::string newPath = jni::Make(env, path); mapbox::sqlite::setTempPath(newPath); fileSource->setResourceCachePath(newPath + DATABASE_FILE); } void FileSource::resume(jni::JNIEnv&) { if (!activationCounter) { activationCounter = optional(1) ; return; } activationCounter.value()++; if (activationCounter == 1) { fileSource->resume(); } } void FileSource::pause(jni::JNIEnv&) { if (activationCounter) { activationCounter.value()--; if (activationCounter == 0) { fileSource->pause(); } } } jni::jboolean FileSource::isResumed(jni::JNIEnv&) { if (activationCounter) { return (jboolean) (activationCounter > 0); } return (jboolean) false; } FileSource* FileSource::getNativePeer(jni::JNIEnv& env, const jni::Object& jFileSource) { static auto& javaClass = jni::Class::Singleton(env); static auto field = javaClass.GetField(env, "nativePtr"); return reinterpret_cast(jFileSource.Get(env, field)); } mbgl::DefaultFileSource& FileSource::getDefaultFileSource(jni::JNIEnv& env, const jni::Object& jFileSource) { FileSource* fileSource = FileSource::getNativePeer(env, jFileSource); assert(fileSource != nullptr); return *fileSource->fileSource; } void FileSource::registerNative(jni::JNIEnv& env) { // Ensure the class for ResourceTransformCallback is cached. If it's requested for the // first time on a background thread, Android's class loader heuristics will fail. // https://developer.android.com/training/articles/perf-jni#faq_FindClass jni::Class::Singleton(env); static auto& javaClass = jni::Class::Singleton(env); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer jni::RegisterNativePeer( env, javaClass, "nativePtr", jni::MakePeer&>, "initialize", "finalize", METHOD(&FileSource::getAccessToken, "getAccessToken"), METHOD(&FileSource::setAccessToken, "setAccessToken"), METHOD(&FileSource::setAPIBaseUrl, "setApiBaseUrl"), METHOD(&FileSource::setResourceTransform, "setResourceTransform"), METHOD(&FileSource::setResourceCachePath, "setResourceCachePath"), METHOD(&FileSource::resume, "activate"), METHOD(&FileSource::pause, "deactivate"), METHOD(&FileSource::isResumed, "isActivated") ); } // FileSource::ResourceTransformCallback // std::string FileSource::ResourceTransformCallback::onURL(jni::JNIEnv& env, const jni::Object& callback, int kind, std::string url_) { static auto& javaClass = jni::Class::Singleton(env); static auto method = javaClass.GetMethod(env, "onURL"); return jni::Make(env, callback.Call(env, method, kind, jni::Make(env, url_))); } } // namespace android } // namespace mbgl