From 197f0ca6b418a27412bfcc7e891ab80949fd8833 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20K=C3=A4fer?= Date: Tue, 11 Apr 2017 17:18:09 +0200 Subject: [android] use AAssetManager instead of libzip --- .../com/mapbox/mapboxsdk/storage/FileSource.java | 10 +- platform/android/config.cmake | 11 +- platform/android/src/asset_file_source.cpp | 113 --------------------- platform/android/src/asset_manager.hpp | 14 +++ platform/android/src/asset_manager_file_source.cpp | 53 ++++++++++ platform/android/src/asset_manager_file_source.hpp | 28 +++++ platform/android/src/file_source.cpp | 13 ++- platform/android/src/file_source.hpp | 4 +- platform/android/src/jni.hpp | 1 - platform/default/default_file_source.cpp | 8 +- 10 files changed, 122 insertions(+), 133 deletions(-) delete mode 100644 platform/android/src/asset_file_source.cpp create mode 100644 platform/android/src/asset_manager.hpp create mode 100644 platform/android/src/asset_manager_file_source.cpp create mode 100644 platform/android/src/asset_manager_file_source.hpp (limited to 'platform') diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/storage/FileSource.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/storage/FileSource.java index a12d8f9954..06676d76a1 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/storage/FileSource.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/storage/FileSource.java @@ -5,6 +5,7 @@ import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.os.Environment; import android.support.annotation.NonNull; +import android.content.res.AssetManager; import com.mapbox.mapboxsdk.Mapbox; import com.mapbox.mapboxsdk.constants.MapboxConstants; @@ -40,8 +41,7 @@ public class FileSource { public static synchronized FileSource getInstance(Context context) { if (INSTANCE == null) { String cachePath = getCachePath(context); - String apkPath = context.getPackageCodePath(); - INSTANCE = new FileSource(cachePath, apkPath); + INSTANCE = new FileSource(cachePath, context.getResources().getAssets()); } return INSTANCE; @@ -107,8 +107,8 @@ public class FileSource { private long nativePtr; - private FileSource(String cachePath, String apkPath) { - initialize(Mapbox.getAccessToken(), cachePath, apkPath); + private FileSource(String cachePath, AssetManager assetManager) { + initialize(Mapbox.getAccessToken(), cachePath, assetManager); } public native void setAccessToken(@NonNull String accessToken); @@ -127,7 +127,7 @@ public class FileSource { */ public native void setResourceTransform(final ResourceTransformCallback callback); - private native void initialize(String accessToken, String cachePath, String apkPath); + private native void initialize(String accessToken, String cachePath, AssetManager assetManager); @Override protected native void finalize() throws Throwable; diff --git a/platform/android/config.cmake b/platform/android/config.cmake index 2e39437109..7c10ba96f8 100644 --- a/platform/android/config.cmake +++ b/platform/android/config.cmake @@ -16,7 +16,6 @@ if ((ANDROID_ABI STREQUAL "armeabi") OR (ANDROID_ABI STREQUAL "armeabi-v7a") OR endif() mason_use(jni.hpp VERSION 3.0.0 HEADER_ONLY) -mason_use(libzip VERSION 1.1.3) mason_use(nunicode VERSION 1.7.1) mason_use(sqlite VERSION 3.14.2) mason_use(gtest VERSION 1.8.0) @@ -34,8 +33,11 @@ macro(mbgl_platform_core) # File source PRIVATE platform/android/src/http_file_source.cpp - PRIVATE platform/android/src/asset_file_source.cpp + PRIVATE platform/android/src/asset_manager.hpp + PRIVATE platform/android/src/asset_manager_file_source.cpp + PRIVATE platform/android/src/asset_manager_file_source.hpp PRIVATE platform/default/default_file_source.cpp + PRIVATE platform/default/asset_file_source.cpp PRIVATE platform/default/local_file_source.cpp PRIVATE platform/default/online_file_source.cpp @@ -76,7 +78,6 @@ macro(mbgl_platform_core) target_add_mason_package(mbgl-core PUBLIC sqlite) target_add_mason_package(mbgl-core PUBLIC nunicode) - target_add_mason_package(mbgl-core PUBLIC libzip) target_add_mason_package(mbgl-core PUBLIC geojson) target_add_mason_package(mbgl-core PUBLIC jni.hpp) target_add_mason_package(mbgl-core PUBLIC rapidjson) @@ -305,10 +306,6 @@ macro(mbgl_platform_test) PRIVATE -fvisibility=hidden ) - target_compile_definitions(mbgl-test - PRIVATE MBGL_ASSET_ZIP=1 - ) - target_link_libraries(mbgl-test PRIVATE mbgl-android PRIVATE -Wl,--gc-sections diff --git a/platform/android/src/asset_file_source.cpp b/platform/android/src/asset_file_source.cpp deleted file mode 100644 index c72b86af5c..0000000000 --- a/platform/android/src/asset_file_source.cpp +++ /dev/null @@ -1,113 +0,0 @@ -#include -#include -#include -#include -#include - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wshadow" -#include -#pragma GCC diagnostic pop - -namespace { - -struct ZipHolder { - ZipHolder(struct zip* archive_) : archive(archive_) {} - - ~ZipHolder() { - if (archive) ::zip_close(archive); - } - - struct zip* archive; -}; - -struct ZipFileHolder { - ZipFileHolder(struct zip_file* file_) : file(file_) {} - - ~ZipFileHolder() { - if (file) ::zip_fclose(file); - } - - struct zip_file* file; -}; - -} - -namespace mbgl { - -class AssetFileRequest : public AsyncRequest { -public: - AssetFileRequest(std::unique_ptr workRequest_) - : workRequest(std::move(workRequest_)) { - } - - std::unique_ptr workRequest; -}; - -class AssetFileSource::Impl { -public: - Impl(const std::string& root_) - : root(root_) { - } - - void request(const std::string& url, FileSource::Callback callback) { - ZipHolder archive = ::zip_open(root.c_str(), 0, nullptr); - if (!archive.archive) { - reportError(Response::Error::Reason::Other, "Could not open zip archive", callback); - return; - } - - struct zip_stat stat; - ::zip_stat_init(&stat); - - std::string path = std::string("assets/") + mbgl::util::percentDecode(url.substr(8)); - - int ret = ::zip_stat(archive.archive, path.c_str(), 0, &stat); - if (ret < 0 || !(stat.valid & ZIP_STAT_SIZE)) { - reportError(Response::Error::Reason::NotFound, "Could not stat file in zip archive", callback); - return; - } - - ZipFileHolder file = ::zip_fopen(archive.archive, path.c_str(), 0); - if (!file.file) { - reportError(Response::Error::Reason::NotFound, "Could not open file in zip archive", callback); - return; - } - - std::shared_ptr buf = std::make_shared(); - buf->resize(stat.size); - - ret = ::zip_fread(file.file, &buf->front(), stat.size); - if (ret < 0) { - reportError(Response::Error::Reason::Other, "Could not read file in zip archive", callback); - return; - } - - Response response; - response.data = buf; - callback(response); - } - - void reportError(Response::Error::Reason reason, const char * message, FileSource::Callback callback) { - Response response; - response.error = std::make_unique(reason, message); - callback(response); - } - -private: - std::string root; -}; - -AssetFileSource::AssetFileSource(const std::string& root) - : thread(std::make_unique>( - util::ThreadContext{"AssetFileSource", util::ThreadPriority::Low}, - root)) { -} - -AssetFileSource::~AssetFileSource() = default; - -std::unique_ptr AssetFileSource::request(const Resource& resource, Callback callback) { - return thread->invokeWithCallback(&Impl::request, resource.url, callback); -} - -} diff --git a/platform/android/src/asset_manager.hpp b/platform/android/src/asset_manager.hpp new file mode 100644 index 0000000000..b87d189514 --- /dev/null +++ b/platform/android/src/asset_manager.hpp @@ -0,0 +1,14 @@ +#pragma once + +namespace mbgl { +namespace android { + +class AssetManager { +public: + static constexpr auto Name() { + return "android/content/res/AssetManager"; + }; +}; + +} // namespace android +} // namespace mbgl diff --git a/platform/android/src/asset_manager_file_source.cpp b/platform/android/src/asset_manager_file_source.cpp new file mode 100644 index 0000000000..6a3113d696 --- /dev/null +++ b/platform/android/src/asset_manager_file_source.cpp @@ -0,0 +1,53 @@ +#include "asset_manager_file_source.hpp" + +#include +#include +#include +#include + +#include +#include + +namespace mbgl { + +class AssetManagerFileSource::Impl { +public: + Impl(AAssetManager* assetManager_) : assetManager(assetManager_) { + } + + void request(const std::string& url, FileSource::Callback callback) { + // Note: AssetManager already prepends "assets" to the filename. + const std::string path = mbgl::util::percentDecode(url.substr(8)); + + Response response; + + if (AAsset* asset = AAssetManager_open(assetManager, path.c_str(), AASSET_MODE_BUFFER)) { + response.data = std::make_shared( + reinterpret_cast(AAsset_getBuffer(asset)), AAsset_getLength64(asset)); + AAsset_close(asset); + } else { + response.error = std::make_unique(Response::Error::Reason::NotFound, + "Could not read asset"); + } + + callback(response); + } + +private: + AAssetManager* assetManager; +}; + +AssetManagerFileSource::AssetManagerFileSource(jni::JNIEnv& env, jni::Object assetManager_) + : assetManager(assetManager_.NewGlobalRef(env)), + thread(std::make_unique>( + util::ThreadContext{"AssetManagerFileSource", util::ThreadPriority::Low}, + AAssetManager_fromJava(&env, jni::Unwrap(**assetManager)))) { +} + +AssetManagerFileSource::~AssetManagerFileSource() = default; + +std::unique_ptr AssetManagerFileSource::request(const Resource& resource, Callback callback) { + return thread->invokeWithCallback(&Impl::request, resource.url, callback); +} + +} // namespace mbgl diff --git a/platform/android/src/asset_manager_file_source.hpp b/platform/android/src/asset_manager_file_source.hpp new file mode 100644 index 0000000000..7a447a2c61 --- /dev/null +++ b/platform/android/src/asset_manager_file_source.hpp @@ -0,0 +1,28 @@ +#pragma once + +#include + +#include "asset_manager.hpp" + +#include + +namespace mbgl { + +namespace util { +template class Thread; +} // namespace util + +class AssetManagerFileSource : public FileSource { +public: + AssetManagerFileSource(jni::JNIEnv&, jni::Object); + ~AssetManagerFileSource() override; + + std::unique_ptr request(const Resource&, Callback) override; + +private: + jni::UniqueObject assetManager; + class Impl; + std::unique_ptr> thread; +}; + +} // namespace mbgl diff --git a/platform/android/src/file_source.cpp b/platform/android/src/file_source.cpp index 20715bf920..16c09b7b52 100644 --- a/platform/android/src/file_source.cpp +++ b/platform/android/src/file_source.cpp @@ -2,21 +2,24 @@ #include -#include - +#include "asset_manager_file_source.hpp" #include "jni/generic_global_ref_deleter.hpp" +#include namespace mbgl { namespace android { // FileSource // -FileSource::FileSource(jni::JNIEnv& _env, jni::String accessToken, jni::String _cachePath, jni::String _apkPath) { +FileSource::FileSource(jni::JNIEnv& _env, + jni::String accessToken, + jni::String _cachePath, + jni::Object assetManager) { // Create a core default file source fileSource = std::make_unique( jni::Make(_env, _cachePath) + "/mbgl-offline.db", - jni::Make(_env, _apkPath)); + std::make_unique(_env, assetManager)); // Set access token fileSource->setAccessToken(jni::Make(_env, accessToken)); @@ -80,7 +83,7 @@ void FileSource::registerNative(jni::JNIEnv& env) { // Register the peer jni::RegisterNativePeer( env, FileSource::javaClass, "nativePtr", - std::make_unique, + std::make_unique>, "initialize", "finalize", METHOD(&FileSource::getAccessToken, "getAccessToken"), diff --git a/platform/android/src/file_source.hpp b/platform/android/src/file_source.hpp index 073e393e05..55e70f34d9 100644 --- a/platform/android/src/file_source.hpp +++ b/platform/android/src/file_source.hpp @@ -2,6 +2,8 @@ #include +#include "asset_manager.hpp" + #include namespace mbgl { @@ -23,7 +25,7 @@ public: static jni::Class javaClass; }; - FileSource(jni::JNIEnv&, jni::String, jni::String, jni::String); + FileSource(jni::JNIEnv&, jni::String, jni::String, jni::Object); ~FileSource(); diff --git a/platform/android/src/jni.hpp b/platform/android/src/jni.hpp index f0c113f754..e5df92e701 100644 --- a/platform/android/src/jni.hpp +++ b/platform/android/src/jni.hpp @@ -13,7 +13,6 @@ extern JavaVM* theJVM; extern std::string cachePath; extern std::string dataPath; -extern std::string apkPath; bool attach_jni_thread(JavaVM* vm, JNIEnv** env, std::string threadName); void detach_jni_thread(JavaVM* vm, JNIEnv** env, bool detach); diff --git a/platform/default/default_file_source.cpp b/platform/default/default_file_source.cpp index 20a3eadc8b..27c3950e2a 100644 --- a/platform/default/default_file_source.cpp +++ b/platform/default/default_file_source.cpp @@ -167,9 +167,15 @@ private: DefaultFileSource::DefaultFileSource(const std::string& cachePath, const std::string& assetRoot, uint64_t maximumCacheSize) + : DefaultFileSource(cachePath, std::make_unique(assetRoot), maximumCacheSize) { +} + +DefaultFileSource::DefaultFileSource(const std::string& cachePath, + std::unique_ptr&& assetFileSource_, + uint64_t maximumCacheSize) : thread(std::make_unique>(util::ThreadContext{"DefaultFileSource", util::ThreadPriority::Low}, cachePath, maximumCacheSize)), - assetFileSource(std::make_unique(assetRoot)), + assetFileSource(std::move(assetFileSource_)), localFileSource(std::make_unique()) { } -- cgit v1.2.1